Skip to main content
Version: v2.0

Invoke an agent

One turn of an agent conversation is one HTTP request.

POST {AGENTA_HOST}/services/agent/v0/invoke?project_id={PROJECT_ID}

This is the endpoint the playground drives. It is served by the agent workflow service, not by the /api surface, so it is not in the API Reference.

DeploymentHost
Cloud (US)https://us.cloud.agenta.ai
Cloud (EU)https://eu.cloud.agenta.ai
Self-hostedyour Agenta origin

The same service also serves POST /services/agent/v0/inspect, which returns the agent workflow's resolved revision plus a ready-made invoke request.

Authentication​

ItemValue
HeaderAuthorization: ApiKey {API_KEY}
Query parameterproject_id={PROJECT_ID}

The project is not read from the request body. The service checks the credential against the Agenta API before the run starts, and returns 401 for an invalid credential or 403 when the key may not run services in that project.

Request headers​

HeaderValuesEffect
Content-Typeapplication/jsonRequired.
Acceptapplication/jsonOne JSON response after the turn finishes.
text/event-streamServer-sent events.
application/x-ndjson, application/jsonlNewline-delimited JSON.
absent or */*The server picks the format that matches what the handler produced.
x-ag-messages-formatvercelMessages and frames use the Vercel AI SDK representation. Absent means the Agenta representation.
x-ag-messages-transcriptlast | fulllast trims the output to the trailing unit of the turn. full returns the whole message list.
x-ag-session-controlforceTake over or attach to an existing run on the session.
x-ag-workflow-embedsresolveResolve @ag.embed references in the configuration.
x-ag-session-ida session idUsed when the body carries no session_id.

Each of the last four headers maps onto a field in the body's flags object (stream, trim, force, resolve). A value in flags wins over the header.

See Chat message format for what each representation looks like.

Request body​

FieldTypeRequiredDefaultDescription
dataobjectNonullThe turn's payload. See below.
session_idstringNoserver-minted1 to 128 characters matching ^[A-Za-z0-9._:-]{1,128}$. When absent, the server mints one and returns it. An invalid value returns 400.
on_busy"reject" | "queue" | "steer"NonullPolicy when this session already has an active execution. Requires session_id.
referencesobjectNonullPoints the run at a stored configuration. See Running a stored agent.
flagsobjectNonullstream, trim, force, resolve. Each is a boolean.
tagsobjectNonullFree-form key-value pairs recorded on the trace.
metaobjectNonullFree-form key-value pairs recorded on the trace.
linksobjectNonull{trace_id, span_id} pairs linking this run to another trace.
selectorobjectNonull{key, path}, used when resolving a reference through an environment.
secretsobjectNonullPer-request secret values.
credentialsstringNonullCredential passed to the run.
versionstringNo"2025.07.14"Request contract version.

Use only letters, numbers, underscores, and hyphens when your client also calls the /api/sessions management endpoints. Their current session ID contract is narrower than the invoke contract.

data​

FieldTypeRequiredDefaultDescription
inputsobjectNonullFor an agent, {"messages": [...]}.
parametersobjectNonullFor an agent, {"agent": {...}}, the agent template.
revisionobjectNonullAn inline workflow revision.
testcaseobjectNonullA test case supplying the inputs.
traceobjectNonullTrace context for the run.
outputsanyNonullReserved.

Running an inline configuration​

Send the whole agent template in data.parameters.agent. Nothing has to be stored first.

curl -N -X POST \
"https://eu.cloud.agenta.ai/services/agent/v0/invoke?project_id=019d952f-0000-0000-0000-000000000000" \
-H "Authorization: ApiKey $AGENTA_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"session_id": "019d952f-0000-0000-0000-000000000001",
"data": {
"inputs": {
"messages": [
{"role": "user", "content": "List the files in the working directory."}
]
},
"parameters": {
"agent": {
"instructions": {"agents_md": "Be terse. Report only what you observed."},
"llm": {
"provider": "openai",
"model": "gpt-5.6-luna",
"connection": {"mode": "agenta"}
},
"tools": [],
"mcps": [],
"skills": [],
"harness": {"kind": "pi_core"},
"runner": {"kind": "sidecar", "permissions": {"default": "allow_reads"}},
"sandbox": {"kind": "local"}
}
}
}
}'

Running a stored agent​

Send references instead of data.parameters. Agenta fetches the stored revision and runs it.

{
"session_id": "019d952f-0000-0000-0000-000000000001",
"references": {
"workflow_revision": { "id": "019d952f-0000-0000-0000-000000000002" }
},
"data": {
"inputs": {
"messages": [
{ "role": "user", "content": "Draft this week's changelog." }
]
}
}
}

A reference is {id, slug, version}; supply whichever you have. id is always sufficient.

FamilyKeys
Workflowworkflow, workflow_variant, workflow_revision
Applicationapplication, application_variant, application_revision
Evaluatorevaluator, evaluator_variant, evaluator_revision
Environmentenvironment, environment_variant, environment_revision

Two rules govern this object:

  • Populate exactly one of the workflow, application, and evaluator families. Two of them together returns 400. The environment keys combine with any of the three.
  • The stored configuration is fetched only when data.parameters is absent. Sending both means the inline parameters run and the reference identifies the run.

JSON response​

With Accept: application/json the response arrives once, after the turn finishes.

{
"version": "2025.07.14",
"status": { "code": 200, "message": "Success" },
"trace_id": "019d952f000000000000000000000003",
"span_id": "019d952f00000004",
"session_id": "019d952f-0000-0000-0000-000000000001",
"data": {
"outputs": {
"messages": [
{
"role": "tool",
"content": "",
"tool_call_id": "call_019d952f",
"tool_name": "bash",
"input": { "command": "ls" }
},
{
"role": "tool",
"content": "AGENTS.md\nREADME.md\n",
"tool_call_id": "call_019d952f",
"is_error": false
},
{
"role": "assistant",
"content": "Two files: AGENTS.md and README.md."
}
],
"stop_reason": "end_turn"
}
}
}
FieldTypeDescription
versionstringResponse contract version.
status.codeintegerRepeated as the HTTP status code.
status.messagestringStatus text.
status.typestring or nullError type, when the run failed.
status.stacktracestring, array of string, or nullPresent on some failures.
trace_idstring or nullThe run's trace.
span_idstring or nullThe run's span.
session_idstring or nullThe resolved session id.
data.outputs.messagesarrayThe folded turn.
data.outputs.stop_reasonstringPresent when the turn produced one. paused means the run stopped for an approval.
data.outputs.pending_interactionobjectPresent when stop_reason is paused. Carries the interaction id, kind, payload, and the derived tool name.

Fields that are null are omitted from the response.

Streaming response​

With Accept: text/event-stream, frames arrive as server-sent events for the length of the turn. With application/x-ndjson or application/jsonl the same objects arrive as newline-delimited JSON.

Add x-ag-messages-format: vercel for the Vercel AI SDK UI Message Stream, which terminates with data: [DONE]. Without it, each frame is a raw Agenta event and there is no terminator. Frame vocabularies for both are in Chat message format.

Response headers​

HeaderPresent when
x-ag-versionalways
x-ag-trace-idthe run produced a trace
x-ag-span-idthe run produced a span
x-ag-session-ida session is in play
baggagea session is in play, carrying ag.session.id=<id>
traceparentboth a trace id and a span id exist
x-vercel-ai-ui-message-stream: v1, x-ag-messages-format: vercel, x-ag-messages-version: v1the Vercel UI Message Stream was requested

Continuing a conversation​

Reuse the same session_id across turns and send the conversation so far in data.inputs.messages.

A turn that stops for an approval ends with stop_reason: "paused". Two ways to answer it exist.

In band. Re-post the paused assistant message with the decision recorded on its tool part, in the same session_id. This is what the playground does. The shape is in Chat message format.

Out of band. Answer the interaction record through the API:

POST /api/sessions/interactions/{interaction_id}/respond

The request needs an Idempotency-Key header. A request without one returns 422.

IDEMPOTENCY_KEY=$(uuidgen) # reuse the same value when you retry

curl -X POST \
"https://eu.cloud.agenta.ai/api/sessions/interactions/019d952f-0000-0000-0000-000000000002/respond" \
-H "Authorization: ApiKey $AGENTA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-d '{"answer": {"approved": true}}'
Body fieldTypeRequiredDescription
answerobjectOne of answer, answersThe answer for the interaction in the path. For a user_approval, {"approved": <bool>}, with an optional message.
answersarrayOne of answer, answersUp to 100 {"interaction_id", "answer"} items for the same paused execution. It must include the interaction in the path.
expected_execution_idstringNoThe execution you expect the interaction to belong to. A mismatch returns 409.

The Idempotency-Key header is a string of at most 255 characters. A retry with the same key and the same answer does not answer twice and returns 202, so a client can retry safely after a network error. The retry reports the current state, which can differ from the first response: for example, execution.state is terminal once another answer has already continued the run. Reusing a key for a different answer returns 409 with the code idempotency_key_reused.

A successful response is 202 Accepted. Once every pending interaction of the paused execution has an answer, the run continues in the background, in a new execution of the same session. The response below is trimmed; interaction carries the full interaction record.

{
"interaction": {
"id": "019d952f-0000-0000-0000-000000000002",
"session_id": "019d952f-0000-0000-0000-000000000001",
"kind": "user_approval",
"status": "responded"
},
"command": {
"id": "019d952f-0000-0000-0000-000000000003",
"state": "pending"
},
"execution": {
"id": "019d952f-0000-0000-0000-000000000004",
"state": "pending_delivery"
}
}

When the paused execution still has other pending interactions, execution.state is awaiting_interactions, command is null, and no new execution starts. Answer the remaining interactions to continue the run.

Related endpoints:

Method and pathPurpose
POST /api/sessions/interactions/queryList interactions for a session.
GET /api/sessions/interactions/{interaction_id}Fetch one interaction.
POST /api/sessions/interactions/{interaction_id}/respondAnswer a pending interaction.
POST /api/sessions/interactions/transitionMove an interaction to another status.

An interaction has a kind of user_approval, user_input, or client_tool, and a status of pending, responded, resolved, or cancelled. To retry a request, reuse its Idempotency-Key. Sending the same answer to an interaction that is already responded is accepted. A different answer to a responded interaction returns 409, and so does any answer to a resolved or cancelled one.

Errors​

StatusCause
400The agent template uses a pre-migration flat key, or an unknown key inside harness, runner, or sandbox. The runner.permissions.default value is not one of the four modes. The session_id does not match the allowed pattern. Two execution reference families are populated at once.
401Missing or invalid credential.
403The credential may not run services in that project.
406Accept asked for a stream but the handler produced a batch response, or the reverse.
410The request names an archived application by its id alone, with no variant or revision reference and no inline configuration. status.type ends in #v0:references:archived. Other request shapes still run on an archived application; see #7110.
4xx / 5xx in status.codeA run that fails returns a JSON body with the real status, even when a stream was requested.