codai docs
Agents

Tools and sub-agents

The built-in tools an agent run can use, the standalone /v1/tools endpoints, and how spawn_agent fans work out to typed sub-agents.

Inside an agent run — or a chat completion with x-codai-server-tools: 1 — the model gets a set of gateway-executed tools. It calls them like any function tool; the gateway runs every call of a turn in parallel and feeds the results back. You never see the tool traffic unless you read the run's steps.

Built-in tools

ToolWhat it doesAvailable when
http_fetchFetch a URL server-side.Your key's tool level allows HTTP (l1_http or higher).
json_queryQuery a JSON document.Same as http_fetch.
exec_pythonRun Python in a sandbox — the "code interpreter" capability.Sandbox enabled on the gateway.
read_artifactRead back a large tool result the gateway spilled to storage instead of inlining.Spilling enabled and at least one tool active.
memory_recall, memory_rememberLong-term memory scoped to your account.Your plan includes persistent memory.
use_skillLoad one of your skills into the loop.At least one skill visible to the key.
web_searchNative web search; { query, max_results 1–10 }.Web search configured on the gateway.
MCP toolsTools exposed by the MCP servers attached to your key.Tool level is not none.
delegate_to_modelcodai's internal single-completion router across the models you may call.Always, when ≥ 2 models are allowed.
spawn_agentA typed sub-agent with its own context and tool loop.See below.

Tool level is a property of your key. none disables every executed tool; l1_http allows network reads; l3_shell and l4_browser unlock the heavier sub-agent roles.

spawn_agent

When server-side tools are on, the model also gets spawn_agent. Unlike delegate_to_model (one completion), a spawned child runs its own loop with its own context. The model picks a role; the gateway picks the tier, tool level and step budget for it.

Prop

Type

RoleTierMax stepsMax tool levelPurpose
exploresmall6l1_httpRead-only facts. The default.
researchsmall8l1_httpweb_search + http_fetch, returns a sourced summary.
codelarge12caller's level (up to l4_browser)Implement and verify; returns diff or output.
verifysmall6l3_shellRun checks, report PASS/FAIL per check.
summarizesmall3l1_httpDigest one source.

Semantics:

  • Parallel by design. Every spawn_agent call in one assistant turn runs concurrently, and concurrently with the turn's other tool calls. The fan-out is capped per turn (default 4); calls past the cap receive {"error":"delegation_fanout_capped"} as their tool result.
  • Children never spawn. A child has spawn_agent removed, runs on the parent's alias with max_tokens: 4096, and bills as a continuation of the parent turn — it does not start a new task.
  • Cost ceiling. Child spend counts toward the request's cost ceiling (default 5 USD); once reached, further spawns return {"error":"request_cost_ceiling"}.
  • Result shape. The child's answer comes back to the parent as an ordinary tool message prefixed SUB-AGENT[<role>] RESULT:.
  • Progress frames. On a streamed chat completion, the gateway emits vendor frames inside the SSE delta so a UI can render live sub-agent cards: {"codai":{"event":"subagent_started","id","role","task"}} and {"codai":{"event":"subagent_done","id","role","ok","preview"}}. Ignore them if you only want text.
  • Invalid arguments → {"error":"invalid_arguments"}; a child that fails → {"error":"sub_agent_failed"}.

spawn_agent is injected only when the request carries no client-side tools of its own — if you send tools, you own the loop and the gateway stays out.

Standalone search and fetch — /v1/tools

The same search and fetch engines are exposed as plain endpoints, so a client-side agent can use them without going through a model. Both need only your codai_ key, count against your per-minute / per-hour request limits (X-RateLimit-* headers, 429 rate_limit_exceeded), and do not create a usage row — they are not model calls.

POST /v1/tools/search

Prop

Type

curl https://ai.codai.ro/v1/tools/search \
  -H "Authorization: Bearer $CODAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "query": "curs BNR euro azi", "max_results": 3, "freshness": "day" }'

Response — every result is verified: the snippet was found on the live page before it was returned.

{
  "results": [
    { "title": "Curs valutar BNR – 23 septembrie 2026", "url": "https://www.bnr.ro/…", "snippet": "1 EUR = 5,0912 RON …", "source": "bnr", "verified": true, "page_age": "2026-09-23" }
  ],
  "provider": "codai",
  "took_ms": 412,
  "cached": false,
  "coverage": 1,
  "sources_tried": ["bnr", "index"],
  "degraded": [],
  "intent": "currency"
}

If the search service is unreachable the gateway answers 503 search_unavailable (type: server_error) — retry later; nothing was charged.

POST /v1/tools/fetch

Prop

Type

curl https://ai.codai.ro/v1/tools/fetch \
  -H "Authorization: Bearer $CODAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://nodejs.org/en/blog/release/v24.0.0", "max_chars": 4000, "focus": "ESM loader hooks" }'
{
  "url": "https://nodejs.org/en/blog/release/v24.0.0",
  "final_url": "https://nodejs.org/en/blog/release/v24.0.0",
  "title": "Node.js 24.0.0 (Current)",
  "byline": "The Node.js Project",
  "description": "…",
  "canonical": "https://nodejs.org/en/blog/release/v24.0.0",
  "lang": "en",
  "content_type": "text/html",
  "content": "## Module customization hooks\n\n…",
  "chars": 3811,
  "truncated": true,
  "took_ms": 688,
  "cached": false
}

Limits: 10 s timeout, 3 MB body cap, at most 3 redirects, and an SSRF guard on every hop — private, loopback and credential-bearing URLs, or non-HTTP schemes, are 400 bad_request. Accepted content types are HTML, plain text, JSON, XHTML, Markdown and XML; a non-2xx upstream is 502 upstream_error with details: { status, url }. Fetches are cached for 15 minutes, searches for 10.

Both endpoints fetch from the public internet on your behalf. Do not pass them user-supplied URLs you have not validated yourself — the SSRF guard protects codai's network, not your intent.

On this page