Tools — Cloud Function reference
Server-side dispatch of MCP or HTTP tools for a registered agent. See the Tools subsystem for the narrative.
registerTool
Caller: authenticated human (the owner of agentId)
onCall — Firebase Callable
registerTool({
agentId: string;
name: string;
kind: 'mcp' | 'http';
url: string;
authToken?: string; // KMS-encrypted at rest; omit for anonymous tools
manifest?: unknown; // skip to let the server fetch it from `url`
}) => {ok: true}
Errors
| Code | Reason |
|---|---|
invalid-argument | Missing agentId/name/kind/url or URL is unparseable |
permission-denied | Caller does not own agentId |
Side effects
- Writes
agents/{agentId}/tools/{name} - KMS-encrypts
authTokenvia keyprojects/axy-ujex/locations/us-central1/keyRings/ujex/cryptoKeys/secrets - If
kind === 'mcp'andmanifestis not supplied, POSTs{jsonrpc: '2.0', id: 1, method: 'tools/list'}tourland stores the response - Audit:
tool.register
listTools
Caller: authenticated agent onCall
listTools({}) => {
tools: Array<{name: string; kind: 'mcp' | 'http'; url: string; manifest: unknown}>
}
Returns only enabled tools. Credentials (authTokenEnc) are never
included.
invokeTool
Caller: authenticated agent onCall
invokeTool({
name: string;
args?: unknown; // tool-defined; for MCP becomes `params.arguments`
timeoutMs?: number; // default 15_000, clamped to 60_000
}) => {status: number; result: unknown}
Errors
| Code | Reason |
|---|---|
invalid-argument | name missing |
not-found | Tool doesn't exist or is disabled |
resource-exhausted | tools.invoke quota exhausted for this owner/month |
internal | Tool returned non-2xx or threw a network error. details.status = HTTP code (0 on network failure). Quota is credited back on network failure. |
Behaviour
- Decrypts
authTokenEnctransiently; injectsAuthorization: Bearer <token>if present - MCP: body
{jsonrpc: '2.0', id: <rand>, method: 'tools/call', params: {name, arguments: args}} - HTTP: body
args ?? {} - Audit:
tool.invokewith{status, ok, error}
getToolCredential
Caller: authenticated agent onCall
getToolCredential({name: string}) => {token: string | null}
Errors
| Code | Reason |
|---|---|
not-found | No such tool |
Returns {token: null} for tools registered without an authToken.
Every successful call is audited as tool.getCredential — use sparingly;
invokeTool is strongly preferred so the plaintext never touches agent
memory.
Firestore state written
| Path | Written by | Contents |
|---|---|---|
agents/{agentId}/tools/{name} | registerTool | Full tool record including authTokenEnc (Uint8Array) + kmsKey path |
audit/{seq} | all four | Hash-chained audit events (actor, action, target, meta) |
Quota bucket
| Bucket | Charged by | Credited by |
|---|---|---|
tools.invoke | invokeTool success or HTTP-level failure | invokeTool network error |
Retention
Tool registrations live until the owner deletes the agent or marks
enabled: false. Audit entries are append-only and retained per the
audit subsystem's own policy.