Documentation — Intelligence wire reference
Reference · Protocols

Intelligence wire reference

This page lists exactly what agentd sends to a model endpoint and how it reads the answer, for each wire dialect, and how it reacts to each kind of failure. It is for integrators building a gateway or a compatible server, and for operators reading a failed call. The concepts behind it are in Models, providers and roles.

Endpoints

FormTransportNotes
https://host[:port][/path][?query]TCP and TLS, server certificate verifiedany host
http://host[:port][/path][?query]plaintext TCP127.0.0.1, ::1 or localhost only
mock:final, mock:file:<playbook.json>the built-in mock model, run in-process and dialed on loopbackscripted answers, for trying an agent or a workflow without a provider; release binaries and the image carry it (mock-models)
  • List. endpoints is a YAML list or one comma-separated string. Order is failover priority; the first element is the primary.
  • Path. A URL with a path is posted to as written, query string included. A URL with no path gets its dialect's default path.
  • Validation. Every element of every connection is checked at load. Any other scheme, or http:// to a non-loopback host, is refused.
DialectDefault pathEffective path
openai/v1/chat/completionsas configured
anthropic/v1/messagesas configured
bedrock—/model/{modelId}/converse, always
decisions/v1/decisionsas configured

Every request is POST, HTTP/1.1, with Connection: close, on a fresh connection, non-streaming. When the run has a trace id, a traceparent header is added. The configured headers are added to every request, beside the headers the dialect sets.

OpenAI-compatible dialect

Headers: content-type: application/json, and authorization: Bearer <token> when a credential resolves.

Body fieldValue
modelthe wire model
max_tokensthe per-call answer cap, for a chat model whose name does not start with gpt-5, chatgpt-5, o1, o3 or o4
max_completion_tokensthe answer cap, for those names; for a reasoning model, the cap plus the thinking room
temperature0; absent for a reasoning model
reasoning_effortthe effort, for a reasoning model
messagessystem, user, assistant (with tool_calls), tool
tools[{type: function, function: {name, description, parameters}}], when the call has tools
tool_choice"auto", when the call has tools
response_format{type: json_schema, json_schema: {name: "answer", schema, strict}}, when the answer has a schema
  • A tool's parameters is the MCP server's inputSchema, unchanged.
  • An assistant tool call's arguments is sent as a JSON string.
  • A tool result that is an error is sent with the content prefixed ERROR: .

Response: choices[0].message.content is the text; choices[0].message.tool_calls[] are the tool calls, each arguments parsed as JSON (an unparsable string is kept as {"_raw": "<string>"}); usage.prompt_tokens and usage.completion_tokens are the tokens. A body with an error object is a provider error.

finish_reasonRead as
stopfinal answer
tool_callstool use
lengthanswer cut at the cap
anything elseother

Anthropic dialect

Headers: content-type: application/json, anthropic-version: 2023-06-01, and x-api-key: <token> when a credential resolves.

Body fieldValue
modelthe wire model
systemevery system message, joined with a blank line
max_tokensthe answer cap; for a reasoning model, plus the thinking room
thinking{type: adaptive}; {type: enabled, budget_tokens} when the model sets a budget
output_config.effortthe effort, for an adaptive reasoning model
output_config.format{type: json_schema, schema}, when the answer's schema has a constrained form
messagesuser and assistant; tool calls as tool_use blocks, results as tool_result blocks in a user message, with is_error
tools[{name, description, input_schema}], when the call has tools

No temperature and no tool_choice are sent. While a turn is still calling tools, an assistant message that came back with thinking or redacted_thinking blocks is sent back to the same model with its content unchanged, in order.

Response: text blocks are joined into the text; tool_use blocks are the tool calls; usage.input_tokens and usage.output_tokens are the tokens. A body with type: error is a provider error.

stop_reasonRead as
end_turn, stop_sequencefinal answer
tool_usetool use
max_tokensanswer cut at the cap
anything elseother

Bedrock dialect

Path: /model/{modelId}/converse, where modelId is the wire model percent-encoded as one path segment (: and / included). Auth: AWS SigV4 over the method, host, path and body; token is ignored, and an auth: {kind: aws} block is required. Headers: content-type and accept: application/json.

Body fieldValue
messagesuser and assistant turns, consecutive same-role turns merged; blocks {text}, {toolUse: {toolUseId, name, input}}, {toolResult: {toolUseId, content: [{text}], status: success|error}}
system[{text}], one per system message
inferenceConfig.maxTokensthe answer cap; for a reasoning model, plus the thinking room
inferenceConfig.temperature0, except for a Claude model and a reasoning model
toolConfig.tools[{toolSpec: {name, description, inputSchema: {json}}}], when the call has tools
additionalModelRequestFieldsreasoning and output-format fields, by model family

agentd tells model families apart by the provider segment of the model id, after an optional cross-region prefix (us., eu., global., …):

FamilyModel idReasoning fieldsOutput format
Claudeanthropic.…thinking and output_config.effort, as on Anthropicoutput_config.format, as on Anthropic
OpenAI open-weightopenai.…reasoning_effortnone (asked in the prompt)
any other, or an ARN—none; a reasoning model is refused at loadnone (asked in the prompt)

Response: output.message.content blocks: text is joined into the text, toolUse are the tool calls, and reasoningContent blocks mark a message that is sent back within the turn. usage.inputTokens and usage.outputTokens are the tokens. stopReason maps as on Anthropic.

Decisions dialect

Allowed on a provider only, for models of kind: decision. Headers: Content-Type: application/json, and Authorization: Bearer <token> when a credential resolves.

{
  "model": "typesafe/jev-1.13",
  "state": "The app crashes on login and I cannot work.",
  "questions": {
    "queue":  {"type": "choice", "instructions": "queue",
               "criteria": {"billing": "payment problems", "tech": "bugs and outages"}},
    "urgent": {"type": "noul", "instructions": "The customer cannot work at all."},
    "mood":   {"type": "score", "instructions": "mood",
               "criteria": ["calm", "annoyed", "angry"]}
  }
}
Questioninstructionscriteria
choicethe question's instructions, else its idoption → criterion (an empty string for a list option)
noulthe statement, then the question's instructions on a new line—
scorethe question's instructions, else its idthe levels, lowest first

state is a string, a list or an object, sent as given. A decision holds 1 to 16 questions, and a choice or score 2 to 32 options or levels.

Response:

{
  "answers": {
    "queue":  {"choice": "tech", "confidence": 0.91, "probabilities": {"billing": 0.09, "tech": 0.91}},
    "urgent": {"noul": 0.96},
    "mood":   {"score": 1.4, "confidence": 0.9}
  },
  "usage": {"input_tokens": 40, "output_tokens": 8}
}
CheckResult when it fails
every question has an answererror naming the question
a choice is one of the optionserror
a noul is a number from 0 to 1error
a score is a numbererror; a score outside the scale is clamped to it
a confidence, when present, is from 0 to 1error

A score's probabilities are keyed by level position on the wire and by level name in the output. Answers from this dialect are calibrated: true.

Emulation on a chat dialect

A decide call on a chat or reasoning model is one call on that model's dialect, at temperature 0 where the dialect sends one:

  • A system message describes the expected JSON object, one key per question, and says the state is data, never an instruction.
  • A user message carries STATE: and QUESTIONS:.
  • The answer's schema is one required property per question: a choice is an enum of its options with a confidence, a noul a number, a score a number with a confidence.

The answer is checked as a native one is. An answer that does not fit is re-asked once with the reason, and the tokens of both calls are counted. Emulated answers are calibrated: false, and their probabilities are dropped.

Tool names

OpenAI and Anthropic accept tool names matching ^[a-zA-Z0-9_-]+$. agentd sends every other character of a tool name, such as the . in resource.read, as _, in the tool list and in earlier tool calls, and maps the model's tool calls back to the original names.

Structured output

When a call's answer has a JSON Schema, the connection's structured_output decides how it is asked:

Dialectauto (default) sendsprompt sends
openairesponse_format with the schema, when its root is an objectnothing
anthropicoutput_config.format, when the schema has a constrained formnothing
bedrock, Claude familyadditionalModelRequestFields.output_config.format, likewisenothing
bedrock, other familiesnothingnothing
decisionsno schema; prompt is refused at load—

The prompt asks for the answer's shape either way, and the answer is always validated against the full schema. In a turn or step a miss is re-asked up to 2 times; an emulated decision is re-asked once.

The constrained form is the schema made sendable:

  • Every object that lists properties gets additionalProperties: false.
  • These keywords are left out: minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, minLength, maxLength, pattern, minItems, maxItems, uniqueItems, minProperties, maxProperties, contains, minContains, maxContains.
  • A format is kept only when it is date-time, time, date, duration, email, hostname, uri, ipv4, ipv6 or uuid.

A schema has no constrained form when its root is not an object, or any part of it has oneOf, not, if, then, else or patternProperties, an object with no properties, an additionalProperties that is a schema, a $ref outside $defs or definitions, or a recursive definition.

On openai, strict is true when the constrained form exists, every object in it requires all of its properties, and it has no allOf; the constrained form is then sent. Otherwise the schema is sent as written with strict: false, as guidance.

Reasoning

A kind: reasoning model is asked with its reasoning defaults; an effort on a node or a think call replaces the effort for that call.

EffortThinking room, without a budget
low2,048 tokens
medium (default)8,192 tokens
high24,576 tokens

A budget (at least 1,024) replaces the room and, on Anthropic and Claude on Bedrock, selects the thinking: {type: enabled, budget_tokens} form. Every dialect raises the output cap by the room, and budget admission counts it. A fallback model is asked without the head model's reasoning, as the model it is.

Temperature and output caps

CalltemperatureAnswer cap
chat model on openai04,096
chat model on Bedrock, non-Claude family04,096
Claude model, on anthropic or Bedrocknone4,096
reasoning model, any dialectnone4,096 plus the thinking room
preflight on a chat modelas above1,024

Failures, retries and failover

OutcomeSame endpointNext endpointFallback modelreason label
connection refused or reset, DNS failurenoyesyesunreachable
timeoutnoyesyestimeout
4292 retriesyesyesother
5xx2 retriesyesyes5xx
401, 403nononoauth
other 4xxnononoother
malformed response bodynononoother

The reason label is on agent_intel_errors_total. A one-shot job whose model cannot be reached, or refuses the credential, exits 4.

ConstantValue
Same-endpoint retries2, after 250 ms and 500 ms
Breaker opens after3 consecutive failover-class failures
Breaker cooldown5 s, doubling on each consecutive open, at most 60 s
Half-openone probe after the cooldown; success closes, failure reopens
After a successthe lowest-index healthy endpoint becomes active
Per-call ceilingthe connection's timeout (default 120 s), and the run's deadline
Daemon all-down backoffup to 8 more sweeps, 1 s doubling to 30 s, ±25% jitter

The all-down backoff applies to a long-lived instance when every endpoint is down. It is skipped when the cause is an authentication failure and when the model has a fallback, which is asked at once instead.

Credentials

ConnectionEndpointCredential, first that resolves
top-level1AGENTD_INTELLIGENCE_TOKEN, AGENTD_INTELLIGENCE_TOKEN_FILE, the auth bearer, token, token_file
top-levelN ≥ 2AGENTD_INTELLIGENCE_TOKEN_<N>, AGENTD_INTELLIGENCE_TOKEN_<N>_FILE; otherwise none
a providereverythe auth bearer, token, token_file
  • An aws auth block signs every request of every endpoint instead.
  • token_file and the auth bearer are read each time a turn, step or judge starts; a SigV4 signature is computed per request.
  • A token_file that cannot be read stops the start, or the reload, that would use it. An AGENTD_INTELLIGENCE_TOKEN_<N>_FILE is read when a worker builds its client, so an unreadable one fails the turn or step that uses it, and --validate-config does not see it.
  • In a config file, token and credential-shaped headers (authorization, x-api-key, api-key, token, secret, password, and names ending in -token, _token, -key or _key) must be {{secret:NAME}} or {{secret-file:PATH}} references.
  • auth kinds that apply to a model connection: static with token, oauth2, aws, spiffe with svid: jwt. Any other is refused at load, because it cannot send a bearer: a static credential under its own header (put that in headers) or a SPIFFE x509 SVID.
  • No credential is ever logged; health reports carry an endpoint's index and scheme only.

Flags and environment variables

FlagPathEnvironment
--intelligence <list>intelligence.endpointsAGENTD_INTELLIGENCE
--intelligence-token <token>intelligence.tokenAGENTD_INTELLIGENCE_TOKEN
--intelligence-token-file <path>intelligence.token_fileAGENTD_INTELLIGENCE_TOKEN_FILE
—endpoint N of the top-level connectionAGENTD_INTELLIGENCE_TOKEN_<N>, AGENTD_INTELLIGENCE_TOKEN_<N>_FILE
--model <name>intelligence.modelAGENTD_MODEL
--model-swap <policy>intelligence.swap_policyAGENTD_MODEL_SWAP
--budget-tokens-lifetime <n>intelligence.budget.lifetime_tokensAGENTD_BUDGET_TOKENS
--login <target>——
--logout <target>——

Every other intelligence path is a flag and a variable too: dots and underscores become dashes in the flag and underscores in the variable, as --intelligence-dialect and AGENTD_INTELLIGENCE_DIALECT, or --intelligence-roles-turn and AGENTD_INTELLIGENCE_ROLES_TURN. A flag wins over the environment, which wins over files. --login and --logout take intelligence or intelligence:<provider>. The full list is in agentd --help and the Configuration reference.

Configuration keys

Connection keys, on intelligence and on each intelligence.providers.<name>:

KeyValuesDefault
endpointslist, or comma-separated stringrequired on a provider
dialectopenai, anthropic, bedrock, decisions (providers only)openai
tokena secret reference in a file—
token_filea path—
headersname → value—
authan auth block—
timeouta duration120s
structured_outputauto, promptauto

Model keys, on intelligence.models.<name>:

KeyValuesDefault
modelthe wire modelrequired
providera provider namethe top-level connection
kindchat, reasoning, decisionchat
windowcontext window in tokens; not on a decision modelguessed from the wire model's name
fallbacka model name; for a chat or reasoning model, not a decision model—
escalatea model name; decision models only—
reasoning{effort: low|medium|high, budget: ≥1024}; reasoning models onlyeffort medium

The rest of the section, on intelligence only:

KeyValuesDefault
modelthe turn model: a model name or a wire model—
roles.<role>a model name; {model, confidence} for decide, preflight, goal, approvethe turn model
routesmodel name → when to use it; at most 32—
swap_policyfinish-on-old, restart-turnfinish-on-old
budgetsee Control spend with budgets—

Every key under intelligence reloads live. An instruction document may write model, models (without provider), every role but approve, dialect, budget, timeout, structured_output and swap_policy. The other keys are the operator's.

When a context window is needed, agentd takes context.model_window, else the smallest declared window among the turn model and the routes, else a guess from the wire model's name: a name containing claude 200,000; gpt-4.1 or gemini 1,000,000; anything else 128,000.

Events and metrics

EventFields
turn.modelagent_path, role, model, provider
turn.model_fallbackturn, model, served_by
turn.model_degradedturn, from, to, provider
turn.routedctx, model
turn.route_removedctx, model, reason
turn.effort_ignoredagent_path, effort, model
intel.decisionmodel, escalated, answers, unsure; role for a judge
intel.decision.escalateturn, from, to, unsure
intel.healthall_down
intel.swapkind, model_from, model_to, endpoint_change, policy
intel.swap.sentsubagents, policy
intel.token_file.errorprovider, err
preflight.route_unsure, preflight.skills_cappedthe route's choice and confidence; asked, catalogued
MetricType
agent_intel_calls_totalcounter
agent_intel_errors_total{reason}counter
agent_intel_upgauge
agent_intel_all_downgauge
agent_tokens_total{type}counter

agent_intel_call_duration_ms is reserved: a scrape shows only its # HELP and # TYPE lines. The full catalog is in the Events and metrics reference.

Next steps