Skip to main content

Agent HTTP Contract

The source of truth is magma_core.protocol.agent. GEN and BENCH use protocol 2.0; endpoint paths remain /v1/.... Typed protocol objects reject unknown fields and enforce strict types. JSON objects inside tools, attributes, memory, extra_keys, and internal_steps can contain agent-specific data. JSON numbers must be finite.

EndpointRequest / response
GET /healthAgentHealth: readiness
GET /v1/infoAgentInfo: identity, protocol and capabilities
POST /v1/responsesAgentRequest → AgentResponse, a JSON array

HTTP and HTTPS carry the same JSON; TLS may terminate at a reverse proxy. No Python inheritance or simulator dependency is required to implement these endpoints.

Health and identity​

A ready server returns:

GET /health
{"status": "ready"}

status is the only health field; its only allowed value and default is "ready". A server that is not ready may return HTTP 503.

An inference-only agent can return:

GET /v1/info
{
"protocol_version": "2.0",
"agent_id": "my-agent",
"agent_version": "0.1.0",
"capabilities": {"inference": true, "coaching": false},
"specialized_coaching": [],
"coaching_resume": false,
"coaching_unavailable_reason": null
}
FieldType and default
protocol_versionString; defaults to "2.0". Consumers check compatibility.
agent_idRequired string identifying the implementation
agent_versionRequired string identifying its version
capabilitiesRequired object mapping capability names to booleans; consumers require inference: true
specialized_coachingList of strings; defaults to []
coaching_resumeBoolean; defaults to false
coaching_unavailable_reasonString or null; defaults to null

Advertise only implemented capabilities. See coaching for correction kinds and resume support. Inference and coaching share protocol_version; there is no separate coaching version field. Local dataset export is discovered through Python entry points, not an HTTP capability.

Inference input​

Request fieldContract
request_idRequired nonempty string
inputsRequired list of AgentInput; an empty list is valid and expects an empty response

Each AgentInput contains:

FieldType, default, and constraint
idRequired strict integer, unique within this request
instructionRequired AgentInstruction, described below
toolsList of JSON objects; defaults to []
attributesJSON object; defaults to {}
memoryJSON object; defaults to {}; agent-owned state
num_outputsStrict positive integer; defaults to 1
extra_keysJSON object; defaults to {}; agent-specific options

AgentInstruction requires type ("user" or "env") and content (string). A user message can introduce a task, answer a question, or provide a rule. An environment message supplies execution feedback. The protocol accepts any string content, including an empty string; it does not impose a parsed environment-payload schema.

attributes supplies scenario context and vocabulary; provided scenarios include declared robot names in known_robots. Values can change between steps. The agent must use the tools, robot names, and arguments available for the current task.

Tool descriptions and private options​

The wire schema accepts JSON objects for tool descriptions. Provided tools use this convention:

{
"name": "press_button",
"description": "Press a button.",
"parameters": {"id": {"description": "Button name.", "type": "str"}}
}

Convert these descriptions into whatever your model or provider expects. Parameter types such as str are MAGMA conventions, not automatically provider JSON Schema types.

Full-history and history-summarized interpret boolean extra_keys.inference_mode as deterministic decoding when true and sampling when false. Full-history also interprets extra_keys.coaching when supported. These are implementation conventions; unknown options are not automatically forwarded to a model.

Response fields and ordering​

AgentResponse is a JSON array of AgentOutput, without an outer outputs object. Return one entry per requested candidate, in input order and then ascending candidate_index, starting at zero. Match request_id and set source_id to the input's id.

Output fieldType, default, and constraint
request_idRequired nonempty string, matching the request
source_idRequired strict integer, matching the input ID
candidate_indexRequired strict nonnegative integer
statusRequired "completed" or "error"
memoryRequired JSON object; complete replacement state for this candidate
internal_stepsList of JSON objects; defaults to []
outputAgentDecision or null; defaults to null; required non-null for completed
errorAgentError or null; defaults to null; required non-null for error

completed requires a decision and no error. error requires an error and no decision. Unused output or error fields may be omitted or null. AgentResponse.validate_request(request) checks the complete candidate count, identifiers, and order; error candidates occupy their normal positions too.

For example, inputs with IDs 7 and 3 requesting two and one candidates respectively must produce (source_id, candidate_index) pairs (7, 0), (7, 1), (3, 0) in that order.

Decisions and tool calls​

Decision fieldContract
sayString; defaults to ""
tool_callsList of ToolCall; defaults to []
Tool-call fieldContract
nameRequired nonempty string
argumentsJSON object; defaults to {}
target_robot_nameRequired nonempty string

Choose either user-facing text or tool calls for a step. The current decision schema validates field types but does not enforce mutual exclusion. GEN and BENCH normalize calls as actions; do not rely on accompanying text being shown. An empty decision is structurally valid but need not make progress. Tool availability, argument validity, robot selection, and task success are checked separately during execution.

Example exchange​

Request
{
"request_id": "demo",
"inputs": [{
"id": 7,
"instruction": {"type": "user", "content": "Say hello."},
"tools": [],
"attributes": {},
"memory": {},
"num_outputs": 1,
"extra_keys": {}
}]
}
Response
[{
"request_id": "demo",
"source_id": 7,
"candidate_index": 0,
"status": "completed",
"memory": {},
"internal_steps": [],
"output": {"say": "Hello!", "tool_calls": []}
}]

For an action, the candidate's output can instead be:

{
"say": "",
"tool_calls": [{"name": "press_button", "arguments": {"id": "sw0"}, "target_robot_name": "panda"}]
}

This assumes the input declares the button tool, sw0, and panda. See the complete interaction for the request and subsequent feedback.

Environment feedback and errors​

Execution feedback arrives in a later input with instruction.type="env". instruction.content is a string; provided executors serialize a JSON payload into that string. A decoded payload may contain:

KeyMeaning
infosFeedback text, including robot/tool outcomes; can describe successful or failed execution
previous_tool_callExecuted actions keyed by robot name, each with name and arguments
errorExecution error text, used by BENCH for failures without robot feedback
failure_reasonAdditional failure description when supplied by the executor

These are executor conventions, not fields of AgentInstruction. Do not assume every payload contains every key, or that infos always means success. Other environment content remains possible under the string contract.

A failure instruction can look like:

{
"type": "env",
"content": "{\"error\":\"The answer called a tool, but this text-only stage requires a user-facing response and does not allow tool calls.\"}"
}

An execution failure describes what happened in the environment. It is distinct from an agent error returned by /v1/responses.

Agent and HTTP errors​

AgentError requires nonempty strings code and message; optional component is a string or null, defaulting to null. The agent defines its error codes.

Failed candidate
[{
"request_id": "demo",
"source_id": 7,
"candidate_index": 0,
"status": "error",
"memory": {},
"internal_steps": [],
"error": {"code": "model_error", "message": "The model returned invalid JSON.", "component": "model"}
}]

A model/API/parsing failure should produce an error candidate inside a valid HTTP response, retaining complete memory and any diagnostic records. A not-ready server may use HTTP 503. FastAPI rejects invalid protocol requests with HTTP 422. Agent-specific validation can also return 422, as in full-history and the minimal server; these HTTP failures have no candidate array.

Memory and internal records​

Interaction state must be recoverable from the supplied memory. Each candidate returns a complete independent replacement; IDs alone cannot identify a conversation, and there is no reset endpoint. Keep model resources loaded, but do not depend on hidden mutable interaction history.

The provided agents read permanent rules from memory.memory_list as a list of strings. The protocol accepts a general JSON object; an agent can define its own additional memory keys. Preserve initial state you accept, or explicitly migrate it.

internal_steps is a list of JSON objects at the inference boundary. Supplied exporters use the more specific InternalStep schema for component, prompt, and raw-output records. See memory and components and coaching records.

Guide: Create a complete server, then connect it to GEN or BENCH.