Skip to main content
Events are the session protocol between your application and a managed Herm agent. Use POST /v1/sessions/{sessionId}/events to send user.* events. Use GET /v1/sessions/{sessionId}/events and GET /v1/sessions/{sessionId}/events/stream to receive agent.* and session.* events.

Event envelope

Every listed or streamed event is wrapped in an envelope:
{
  "id": "evt_123",
  "type": "agent.message",
  "sessionId": "session_123",
  "sequence": 6,
  "status": "complete",
  "payload": {
    "type": "agent.message",
    "delta": false,
    "content": [{ "type": "text", "text": "Hello!" }]
  },
  "processedAt": "2026-06-20T23:28:02.772Z",
  "createdAt": "2026-06-20T23:28:02.773Z"
}
FieldTypeDescription
idstringGateway event ID.
typestringEvent type, duplicated from payload.type.
sessionIdstringSession ID.
sequenceintegerMonotonic sequence number within the session.
statusstringEvent processing status.
payloadobjectEvent-specific payload.
processedAtstringISO timestamp when processing completed, when available.
createdAtstringISO timestamp when the event was created.

Shared types

Text content block

{ "type": "text", "text": "Hello" }
Text content arrays contain 1 to 100 text blocks. Each text value can be up to 20,000 characters.

Stop reason

session.status_idle.stop_reason is one of:
{ "type": "end_turn" }
{ "type": "error", "message": "The runtime failed." }
{ "type": "requires_action", "event_ids": ["custom_toolu_123"] }
When type is requires_action, send the matching user.* response event.

User events

User events are accepted by POST /v1/sessions/{sessionId}/events.

user.message

Starts a new agent turn.
{
  "type": "user.message",
  "content": [{ "type": "text", "text": "Say hello in one sentence." }]
}
FieldTypeRequiredDescription
typestringYesMust be user.message.
contenttext block[]YesUser message content.
Only one user.message is allowed per request. A new user.message is rejected while another turn is already running.

user.steer

Adds steering text to the current session without starting a normal prompt.
{
  "type": "user.steer",
  "message": "Keep the answer short and cite files you change."
}
FieldTypeRequiredDescription
typestringYesMust be user.steer.
messagestringYesSteering instruction.

user.interrupt

Interrupts the active turn.
{
  "type": "user.interrupt",
  "message": "Stop this run."
}
FieldTypeRequiredDescription
typestringYesMust be user.interrupt.
messagestringNoOptional reason or UI note.

user.tool_confirmation

Allows or denies a built-in or MCP tool call that requires approval.
{
  "type": "user.tool_confirmation",
  "tool_use_id": "toolu_123",
  "result": "allow",
  "scope": "once"
}
FieldTypeRequiredDescription
typestringYesMust be user.tool_confirmation.
tool_use_idstringYesid from agent.tool_use or agent.mcp_tool_use.
resultstringYesallow or deny.
scopestringNoonce, session, or always. Defaults to once when omitted.

user.custom_tool_result

Returns the result of an application-owned custom tool.
{
  "type": "user.custom_tool_result",
  "tool_use_id": "custom_toolu_123",
  "content": [{ "type": "text", "text": "Order #123 ships tomorrow." }],
  "is_error": false
}
FieldTypeRequiredDescription
typestringYesMust be user.custom_tool_result.
tool_use_idstringYesid from agent.custom_tool_use.
contenttext block[]YesTool result content shown to the model.
is_errorbooleanNoDefaults to false. Set to true when your tool failed.

user.clarify_result

Answers an agent clarification request.
{
  "type": "user.clarify_result",
  "request_id": "clarify_123",
  "answer": "Use the production environment."
}
FieldTypeRequiredDescription
typestringYesMust be user.clarify_result.
request_idstringYesrequest_id from agent.clarify_request.
answerstringYesUser answer. Empty string means skip.

user.sudo_result

Supplies a sudo password for a blocked runtime request.
{
  "type": "user.sudo_result",
  "request_id": "sudo_123",
  "password": "correct-horse-battery-staple"
}
FieldTypeRequiredDescription
typestringYesMust be user.sudo_result.
request_idstringYesRuntime request ID.
passwordstringYesPassword value forwarded to Hermes.

user.secret_result

Supplies a requested secret value.
{
  "type": "user.secret_result",
  "request_id": "secret_123",
  "value": "secret-value"
}
FieldTypeRequiredDescription
typestringYesMust be user.secret_result.
request_idstringYesRuntime request ID.
valuestringYesSecret value forwarded to Hermes.

Session events

Session events describe turn status and session metadata changes.

session.status_running

The agent turn is running.
{ "type": "session.status_running" }

session.status_idle

The agent turn ended, errored, or paused for required action.
{
  "type": "session.status_idle",
  "stop_reason": { "type": "end_turn" }
}
{
  "type": "session.status_idle",
  "stop_reason": {
    "type": "requires_action",
    "event_ids": ["custom_toolu_123"]
  }
}
FieldTypeDescription
typestringsession.status_idle.
stop_reasonobjectWhy the turn is idle.

session.title_updated

Live-only event emitted when the gateway generates a session title.
{
  "type": "session.title_updated",
  "title": "Holiday campaign planning"
}
This event is not stored in the persisted event history.

Agent events

Agent events are emitted by the Hermes runtime through the gateway.

agent.message

Assistant response content.
{
  "type": "agent.message",
  "content": [{ "type": "text", "text": "Hello!" }],
  "delta": false
}
FieldTypeDescription
contenttext block[]Assistant text.
deltabooleantrue for streaming chunks, false for complete durable messages.

agent.thinking

Reasoning content emitted by the model or runtime.
{
  "type": "agent.thinking",
  "content": [{ "type": "text", "text": "I need to inspect the repo." }],
  "delta": true
}
FieldTypeDescription
contenttext block[]Reasoning text.
deltabooleantrue for streaming chunks, false for finalized durable reasoning.

agent.tool_use

Built-in Hermes tool call.
{
  "type": "agent.tool_use",
  "id": "toolu_123",
  "tool": "terminal",
  "input": { "command": "pwd" },
  "status": "running",
  "preview": "pwd",
  "requires_action": true
}
FieldTypeDescription
idstringTool use ID.
toolstringTool name.
inputobjectTool input.
statusstringCurrently running.
previewstringOptional human-readable preview.
requires_actionbooleanPresent when the tool requires user.tool_confirmation.

agent.tool_result

Built-in Hermes tool result.
{
  "type": "agent.tool_result",
  "tool_use_id": "toolu_123",
  "tool": "terminal",
  "status": "completed",
  "content": [{ "type": "text", "text": "/workspace" }],
  "is_error": false
}
FieldTypeDescription
tool_use_idstringID of the matching agent.tool_use.
toolstringTool name.
statusstringcompleted or failed.
contenttext block[]Tool result text.
is_errorbooleanWhether the tool result is an error.

agent.mcp_tool_use

MCP tool call. Shape matches agent.tool_use.
{
  "type": "agent.mcp_tool_use",
  "id": "mcptoolu_123",
  "tool": "mcp_github_create_issue",
  "input": { "title": "Bug" },
  "status": "running",
  "requires_action": true
}

agent.mcp_tool_result

MCP tool result. Shape matches agent.tool_result.
{
  "type": "agent.mcp_tool_result",
  "tool_use_id": "mcptoolu_123",
  "tool": "mcp_github_create_issue",
  "status": "completed",
  "content": [{ "type": "text", "text": "Created issue #42." }],
  "is_error": false
}

agent.custom_tool_use

Application-owned custom tool request. Your application must execute the tool and return user.custom_tool_result.
{
  "type": "agent.custom_tool_use",
  "id": "custom_toolu_123",
  "tool": "check_order_status",
  "input": { "order_id": "123" }
}
FieldTypeDescription
idstringTool use ID to return as user.custom_tool_result.tool_use_id.
toolstringCustom tool name from the agent configuration.
inputobjectModel-supplied tool input.

agent.clarify_request

Blocking clarification question from the agent.
{
  "type": "agent.clarify_request",
  "request_id": "clarify_123",
  "question": "Which environment should I deploy to?",
  "choices": ["Staging", "Production"]
}
FieldTypeDescription
request_idstringID to return as user.clarify_result.request_id.
questionstringQuestion to display to the user.
choicesstring[] or nullMultiple-choice options, or null for open-ended answers.

agent.thread_message_sent

Parent agent delegated work to a subagent or thread.
{
  "type": "agent.thread_message_sent",
  "thread_id": "thread_123",
  "content": [{ "type": "text", "text": "Research deployment options." }]
}

agent.thread_message_received

Parent agent received a subagent or thread result.
{
  "type": "agent.thread_message_received",
  "thread_id": "thread_123",
  "content": [{ "type": "text", "text": "Use the existing deployment." }]
}

Custom tool handling

Custom tools are host-executed. Herm only brokers the request and response.
  1. Declare a custom_tool in the agent’s tools array.
  2. The model calls the tool during a turn.
  3. The stream emits agent.custom_tool_use with the tool id, tool name, and input.
  4. The stream emits session.status_idle with stop_reason.type: "requires_action" and the custom tool ID.
  5. Your application executes the tool.
  6. Your application posts user.custom_tool_result with tool_use_id equal to the agent.custom_tool_use.id.
  7. The gateway forwards the result to Hermes and the paused turn continues streaming.
Custom tools are not governed by Herm permission policies because they do not run inside the Hermes sandbox. Your application is responsible for authorization, validation, idempotency, retries, and side-effect safety.