For AI agents: a documentation index is available at https://www.plungeai.com/docs/llms.txt. Append .md to any page URL, or send Accept: text/markdown, to get markdown. Setup instructions for agents are at https://www.plungeai.com/docs/agents.md. One ozk_ key opens every plane, models included.

Documentation Index: fetch the complete documentation index at /llms.txt. Use this file to discover all available pages before exploring further.

A tool agent is any active registry agent with a typed invocation contract. The tools plane is the shortest path from "I want Brave search" to a result: three routes, one security check, one execution path. Every call becomes a one-task workflow on the engine, so it lands in your execution history and carries an x-request-id you can trace (Traces).

Discover  ──►  GET  /v1/tools                 who is callable (the active catalog)
Inspect   ──►  GET  /v1/tools/:id             the contract: operations, params, examples
Execute   ──►  POST /v1/tools/:id/execute     contract check → trust fence → engine → result

Auth: Authorization: Bearer $PLUNGE_API_KEY (an ozk_ key — see Authentication & keys).

6.1 List the catalog — GET /v1/tools

Returns the active registry agents as summary cards. Paging: limit (default 50, max 100) and offset. The response count is the size of the page you received, not the catalog total — page until a short page comes back.

curl -s "https://api.plungeai.com/v1/tools?limit=100" \
  -H "Authorization: Bearer $PLUNGE_API_KEY"

Response shape: { "tools": [ { "id", "type": "agent", "name", "description", "category", "tags": [...], "status": "active", "credential": {...}, ... } ], "count" }. credential says what the agent runs on: { "tier": "platform" } (our keys — nothing to set up) or { "tier": "connection", "provider", "method": "oauth" | "api_key" | "wallet" } (the caller's own account at that provider — see Connectors). Tags worth reading: gated:<operation> marks operations the trust fence will refuse unattended (see 6.4), status:active is the only status this route lists.

On 2026-09-18 the catalog had 92 active tool agents in 14 categories (GET /v1/agents/categories gives the live breakdown; the same query backs GET /v1/agents, so the two lists are identical — the difference is how you call them).

6.2 Inspect the contract — GET /v1/tools/:id

curl -s "https://api.plungeai.com/v1/tools/brave-agent" \
  -H "Authorization: Bearer $PLUNGE_API_KEY"
FieldMeaning
agent_id, name, descriptionthe card identity
operations[]{ name, description?, required_params? } — the verbs the agent accepts as operation; an agent with no operations takes a prompt (or its soleRequiredParam)
inputSchemaJSON Schema (type: object, properties, required, additionalProperties) for params; per-operation requireds live on operations[].required_params
examples[]{ title, cnl } — copy-paste CNL task snippets from the card's demonstrations
output_typeprose description of what comes back
credential{ tier: "platform" } or { tier: "connection", provider, method } — the same value the list carries; GET /v1/tools/stripe-agent answers { "tier": "connection", "provider": "stripe", "method": "api_key" }
soleRequiredParampresent when exactly one string param is required — a bare prompt is mapped onto it
credentialsfilled by surfaces that know the user's connections; absent here

A connection-tier agent says so in the same card:

curl -s "https://api.plungeai.com/v1/tools/stripe-agent" \
  -H "Authorization: Bearer $PLUNGE_API_KEY"

Unknown id → 404 unknown_tool (also in the X-Error-Code header):

curl -s -o /dev/null -w '%{http_code} %header{x-error-code}\n' \
  "https://api.plungeai.com/v1/tools/no-such-agent" \
  -H "Authorization: Bearer $PLUNGE_API_KEY"

6.3 Execute — POST /v1/tools/:id/execute

Body (JSON by default; the same fields as YAML with Content-Type: text/yaml). The tool's fields may be sent bare at the root, exactly as the agent's README documents them ({"expression": "7*6"}); params: is still accepted and wins on a name clash.

FieldTypeNotes
operationstringone of operations[].name; omit for prompt-only agents
the tool's fieldsper the contractbare at the root (query, count, expression, …); validated against the contract
paramsobjectthe same fields wrapped; merged over the bare ones. Names that collide with task-envelope fields (agent, id, type, …) are reserved and rejected either way
promptstringfree-text input; satisfies missing requireds on prompt-capable agents
formatjson · yaml · markdown · textresponse negotiation; Accept and the request Content-Type also count (default JSON, YAML in → YAML out)

Order of evaluation, from orchestration/api-gateway/routes/tools.ts:

  1. Contract validation. reserved names, or missing requireds on a prompt-less call → 422 invalid_params with { missing, reserved, warnings, contract } — the contract is echoed so you can fix the call without a second request.
  2. The trust fence (checkAgentCall, mode unattended) → 403 refused or 409 approval_required — see 6.4. Nothing is executed and no execution row is written.
  3. Execution. A workflow_executions row opens under your user (execution_id = the request's trace id), the engine runs the one-task wrapper, the row closes with the result.

Success (200):

{ "ok": true, "content": "…markdown or text…", "outcome": "ok", "execution_id": "…", "request_id": "…" }
curl -s -X POST "https://api.plungeai.com/v1/tools/brave-agent/execute" \
  -H "Authorization: Bearer $PLUNGE_API_KEY" -H "Content-Type: application/json" \
  -d '{"prompt":"cloudflare workers pricing","count":3}'

Bare fields, YAML in → YAML out (the Content-Type mirror):

curl -s -X POST "https://api.plungeai.com/v1/tools/calculator-tool-agent/execute" \
  -H "Authorization: Bearer $PLUNGE_API_KEY" -H 'Content-Type: text/yaml' --data-binary $'expression: "7*6"\n'

Operation form (the weather agent takes location; here the contract says what is missing):

curl -s -w '\n%{http_code}\n' -X POST "https://api.plungeai.com/v1/tools/weather-agent/execute" \
  -H "Authorization: Bearer $PLUNGE_API_KEY" -H "Content-Type: application/json" \
  -d '{"operation":"current","params":{}}'

6.4 Outcomes and the trust fence

An agent that cannot do the job answers with a structured outcome, not prose (core/core-base/agent-outcome.ts). The tools plane maps outcomes onto HTTP (routes/_util.ts outcomeStatus):

outcomeHTTPerror.codeWhat to do
ok200—read content
needs_input422invalid_paramsfix params — error.detail and the echoed contract say how
needs_connection424connection_requiredthe account behind the call has not connected this provider — error.connect names the way in, see Connectors
needs_api_key424credential_requiredthe agent needs a key the account has not stored — error.connect names the way in
unavailable503agent_unavailableupstream/provider down — retry later or pick another agent
error502execution_failedthe agent failed; error.message carries the agent's own text

The error body is { "error": { "code", "message", "outcome", "detail"?, "content"?, "contract"?, "connect"? } } plus an X-Error-Code header. On a 424, connect is { "provider", "method", "link": "POST /v1/connections/<provider>/link" }; the Markdown, YAML and text wires print it as a connect: line under the execution footer.

The trust fence (core/core-base/call-agent.ts) runs before every execution and cannot be turned off from the API:

  • Always-gated operations — buy, purchase, fetch_paid, send, transfer, pay, send_payment, withdraw, shop — plus any gated:<op> tag on the card. On this unattended surface they return 403 refused (a human-in-the-loop surface such as Studio or a harness mission with an explicit allow-list returns 409 approval_required instead).
  • Guarded categories — agents in the payment and blockchain categories are refused unattended unless a mission's allowed_agents names them.
  • Not active — a card that is not status:active is 403 agent_not_active; an unknown id is 404 unknown_tool.
curl -s -w '\n%{http_code}\n' -X POST "https://api.plungeai.com/v1/tools/resend/execute" \
  -H "Authorization: Bearer $PLUNGE_API_KEY" -H "Content-Type: application/json" \
  -d '{"operation":"send","params":{"from":"hello@example.com","to":"nobody@example.com","subject":"x","text":"x"}}'

A refusal writes no execution row — a denial is not a run.

6.5 The catalog by category (live 2026-09-18)

Ids are exact; GET /v1/tools/<id> is the source of truth for operations and for credential. Credential is that field: platform runs on our keys; connection needs the caller's own account at the named provider, connected once over the API (chapter 7). A card whose agent also needs an account that is not yet in the machine-readable table (core/core-base/credential-tiers.ts) reads platform; those are named in the row.

CategoryAgentsCredential
search (14)brave-agent, exa-agent, firecrawl-agent, tavily-agent, serper-agent, serpapi-agent, crawl4ai-agent, browserbase, arxiv-search, wikipedia-search, newsapi-get-articles, nyt-api, product-hunt-agent, branding-agentplatform
tools (23)calculator-tool-agent, markitdown, weather-agent, wolfram-alpha-full-results, data-analyst, code-reviewer, technical-writer, research-analyst, research-team, learn, pdf-worker, pptx-worker, xlsx-worker, ms-office-worker, report-worker, render-worker, cloud-browser-agent, gemini-file-search, google-docs-export-worker, n8n-converter, concierge, agentic-agent, universal-agentplatform (google-docs-export-worker: connection · google)
ai (3)llm-agent, vision-agent, skill-agentplatform
google-workspace (25)google-gmail, google-calendar, google-drive, google-docs, google-sheets, google-slides, google-forms, google-tasks, google-contacts, google-chat, google-meet, google-keep, google-classroom, google-admin, google-vault, google-analytics, google-search-console, google-ads, google-merchant-center, google-business-profile, google-books, google-youtube, google-translate, cloud-natural-language, google-workspace-assistantconnection · google · OAuth (google-books, google-translate, cloud-natural-language: platform)
microsoft-365 (12)microsoft-outlook-mail, microsoft-outlook-calendar, microsoft-outlook-contacts, microsoft-onedrive, microsoft-sharepoint, microsoft-teams, microsoft-todo, microsoft-planner, microsoft-onenote, microsoft-excel, microsoft-word, microsoft-powerpointconnection · azure · OAuth
coding-agents (1)gitlab-agentconnection · gitlab · OAuth (a personal access token works too)
communication (2)resend, cloudflare-email-agentplatform — send/send_batch gated
media (2)image-gen-agent, video-gen-agent (generate_video gated)platform
financials (1)sec-agentplatform
entertainment (2)sports-schedule-agent, tv-listings-agentplatform
ecommerce-agents (2)amazon-shopping-agent, shopping-zinc (buy gated)platform — amazon-shopping-agent also needs an Amazon retailer login, made in Studio
payment (2)x402-wallet-agent (fetch_paid gated), crossmint-agentx402-wallet-agent: connection · x402-wallet · wallet; crossmint-agent: platform — guarded category
blockchain (2)circle-agent, circle-wallet-agentplatform — the Circle wallet is connected in Studio; guarded category
shopping (1)x402-broker (execute gated)platform — needs a wallet connected in Studio

6.6 Using tools from your own LLM loop

The tools plane is designed to sit behind any function-calling model — no SDK required:

  1. GET /v1/tools/:id for the agents you want; turn each contract into a function definition (name = agent id, parameters = inputSchema, one function per operations[].name if you want the model to pick operations).
  2. Send the definitions to your model as tools (any provider — the models plane works too).
  3. When the model returns a tool call, POST /v1/tools/<id>/execute with { "operation", "params" }.
  4. Feed content back as the tool result. On 422 feed back error.message + error.detail — the model fixes its own params. On 403 refused tell the user a human has to approve that action.

Every hop carries x-request-id; keep it in your logs and GET /v1/traces/:id shows the run. For a server-side loop that already does all of this (discover → inspect → execute with an approval gate), call the concierge agent on the agents plane.

Planned: TI-34

The docs assistant is not available yet. You can hand these docs to your own assistant instead.