Run Message Agent

Runtime contract

The generated OpenAPI operation omits the JSON request body. Send the body shown here; an empty body is not a valid request. The generated response example also does not fully reflect the current A2A envelope.

Start the example server below and set the same OS_SECURITY_KEY in the client terminal. These examples target reference-agent on port 7777. On deployments using scoped bearer authorization, this operation requires agents:run (or a matching broader grant). The authenticated principal determines user identity; X-User-ID is only anonymous attribution and cannot override it.

The outer id correlates the request and response. messageId identifies the submitted message. contextId becomes the Agno session ID; omit it to let the server create a session, or reuse a session owned by the same principal and component.

Request

curl -X POST "http://localhost:7777/a2a/agents/reference-agent/v1/message:send" \
  -H "Authorization: Bearer $OS_SECURITY_KEY" \
  -H "Content-Type: application/json" \
  --data '{
  "jsonrpc": "2.0",
  "id": "request-1",
  "method": "message/send",
  "params": {
    "message": {
      "role": "user",
      "messageId": "message-1",
      "contextId": "agent-session",
      "parts": [
        {
          "kind": "text",
          "text": "Hello"
        }
      ]
    }
  }
}'

Response

The response result is the Task itself: use result.id for the Agno run ID, result.contextId for its session, and result.status.state for status. There is no result.task wrapper. JSON field names use camelCase. A representative envelope is:

{
  "jsonrpc": "2.0",
  "id": "request-1",
  "result": {
    "id": "returned-run-id",
    "contextId": "agent-session",
    "kind": "task",
    "status": {
      "state": "completed"
    },
    "history": [
      {
        "role": "agent",
        "messageId": "returned-message-id",
        "kind": "message",
        "contextId": "agent-session",
        "taskId": "returned-run-id",
        "parts": [
          {
            "kind": "text",
            "text": "Example answer"
          }
        ]
      }
    ]
  }
}

Text output is carried in result.history[*].parts; media can also appear in result.artifacts. Optional fields may be absent or null.

By default the call waits for the result (HTTP 200). Setting params.configuration.blocking=false requests background execution and returns HTTP 202; use task polling with the returned run and session IDs. This requires the server's background-execution and database prerequisites.

Example server

The examples in this A2A API reference use this local server. Install dependencies and set a model key and a shared server key in the server terminal:

uv pip install -U "agno[os,a2a]" openai sqlalchemy
export OPENAI_API_KEY=your-openai-api-key
export OS_SECURITY_KEY=your-local-server-key

Save as a2a_reference.py and run python a2a_reference.py:

from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.models.openai import OpenAIChat
from agno.os import AgentOS
from agno.team import Team
from agno.workflow import Workflow, Step, StepInput, StepOutput

db = SqliteDb(db_file="tmp/a2a-reference.db")
agent = Agent(id="reference-agent", name="Reference Agent", model=OpenAIChat(id="gpt-5.4-mini"), db=db)
team = Team(
    id="reference-team",
    name="Reference Team",
    model=OpenAIChat(id="gpt-5.4-mini"),
    members=[Agent(name="Writer", model=OpenAIChat(id="gpt-5.4-mini"))],
    db=db,
)

def echo(step_input: StepInput) -> StepOutput:
    return StepOutput(content=step_input.input)

workflow = Workflow(id="reference-workflow", name="Reference Workflow", steps=[Step(name="echo", executor=echo)], db=db)
agent_os = AgentOS(agents=[agent], teams=[team], workflows=[workflow], a2a_interface=True)
app = agent_os.get_app()

if __name__ == "__main__":
    agent_os.serve(app="a2a_reference:app", host="127.0.0.1", port=7777)

In the client terminal, set OS_SECURITY_KEY to the same value. Agent and team runs use the model provider; the example workflow echoes its input locally. Use a distinct contextId for each component's session.

POST/a2a/agents/{id}/v1/message:send

Send a message to an Agno Agent (non-streaming). The Agent is identified via the path parameter '{id}'. Optional: Pass user ID via X-User-ID header (recommended) or 'userId' in params.message.metadata.

Path Parameters

id*Id

Response Body

application/json

application/json

curl --request POST 'https://example.com/a2a/agents/string/v1/message:send'
{  "jsonrpc": "2.0",  "id": "request-123",  "result": {    "task": {      "id": "task-456",      "context_id": "context-789",      "status": "completed",      "history": [        {          "message_id": "msg-1",          "role": "agent",          "parts": [            {              "kind": "text",              "text": "Response from agent"            }          ]        }      ]    }  }}