Skip to main content
Version: v2.0

Batch runs

Agenta has no endpoint that accepts a list of inputs and runs an agent once per entry. POST /services/agent/v0/invoke takes one message list and produces one turn. The request body carries data.inputs as a single object, not an array.

To run an agent over many inputs, send one request per input and manage the fan-out in your own code.

One request per input

# /// script
# requires-python = ">=3.10"
# dependencies = ["httpx>=0.27"]
# ///
import asyncio
import os
import uuid

import httpx

BASE = "https://eu.cloud.agenta.ai"
PROJECT_ID = "019d952f-0000-0000-0000-000000000000"
REVISION_ID = "019d952f-0000-0000-0000-000000000002"
API_KEY = os.environ["AGENTA_API_KEY"]

INPUTS = [
"Summarize ticket 4821.",
"Summarize ticket 4822.",
"Summarize ticket 4823.",
]

CONCURRENCY = 4


async def run_one(client: httpx.AsyncClient, gate: asyncio.Semaphore, text: str) -> dict:
async with gate:
response = await client.post(
f"{BASE}/services/agent/v0/invoke",
params={"project_id": PROJECT_ID},
headers={
"Authorization": f"ApiKey {API_KEY}",
"Accept": "application/json",
"Content-Type": "application/json",
},
json={
"session_id": uuid.uuid4().hex,
"references": {"workflow_revision": {"id": REVISION_ID}},
"data": {"inputs": {"messages": [{"role": "user", "content": text}]}},
},
timeout=300.0,
)
return response.json()


async def main() -> None:
gate = asyncio.Semaphore(CONCURRENCY)
async with httpx.AsyncClient() as client:
results = await asyncio.gather(
*(run_one(client, gate, text) for text in INPUTS)
)
for text, result in zip(INPUTS, results):
outputs = (result.get("data") or {}).get("outputs") or {}
messages = outputs.get("messages") or []
reply = messages[-1].get("content") if messages else ""
print(text, "->", reply)


asyncio.run(main())

Field-by-field detail for the request and the response is in Invoke an agent.

Choosing session ids

The session_id decides whether the runs share a conversation.

PatternEffect
A fresh session_id per inputEach input runs as its own conversation, with its own session folder. Nothing carries over.
One session_id for every input, with the growing history in data.inputs.messagesOne conversation. Each turn sees the previous ones, and the session folder persists across them.
No session_idThe server mints one per request and returns it in session_id and in the x-ag-session-id response header.

See Sessions and versions.

What the client handles

ConcernBehaviour
ConcurrencyThere is no server-side queue for these requests. Bound the fan-out in your own code.
FailuresEach run reports its own outcome in status.code. A failed run does not affect the others.
ApprovalsUnder a runner.permissions.default of ask or allow_reads, a run can stop with stop_reason: "paused" and wait for an approval. A default of allow never pauses. See Permissions.
OrderingConcurrent runs complete in any order.

Evaluation runs

Agenta has a separate fan-out engine for evaluations. An evaluation run takes a testset revision and a workflow revision, and invokes the workflow once per testcase, bounded by data.concurrency.batch_size. It stores each result and computes metrics.

Method and pathPurpose
POST /api/simple/testsets/Create a testset and its rows in one call. The response carries the revision_id.
POST /api/simple/evaluations/Create an evaluation run. This also starts it.
GET /api/simple/evaluations/{evaluation_id}Read the run's status at data.status.
POST /api/simple/evaluations/{evaluation_id}/stopStop a running evaluation.
POST /api/evaluations/results/queryRead the per-testcase results.
POST /api/evaluations/metrics/queryRead the run's metrics.

The run's steps are revision ids:

{
"evaluation": {
"name": "Ticket summaries",
"data": {
"testset_steps": {"019d952f-0000-0000-0000-000000000010": "auto"},
"application_steps": {"019d952f-0000-0000-0000-000000000002": "auto"},
"repeats": 1,
"concurrency": {"batch_size": 10, "max_retries": 0, "retry_delay": 0}
}
}
}

Two constraints apply:

  • A run carries exactly one entry in application_steps. A run with more than one is never dispatched and stays in its running state.
  • Each testcase is filtered against the target workflow's declared input schema before the call. The agent workflow declares one input, messages, so a testset column with any other name does not reach the agent.
note

The playground's run-all control does not apply to agents. An agent runs from the chat composer, one turn at a time, so there are no testcase rows to fan out in the playground.