Skip to content

Logs And Streams

Agirunner exposes several live and queryable observability surfaces.

These routes are what make the dashboard feel operational instead of static, and they are also the main way to build external observers around workflow execution.

  • POST /api/v1/logs/ingest
  • GET /api/v1/logs
  • GET /api/v1/logs/:id
  • GET /api/v1/logs/stream
  • GET /api/v1/logs/export
  • GET /api/v1/logs/stats
  • GET /api/v1/events
  • GET /api/v1/events/stream

POST /api/v1/logs/ingest

Scope: worker

{
"entries": [
{
"trace_id": "11111111-1111-1111-1111-111111111111",
"span_id": "22222222-2222-2222-2222-222222222222",
"source": "runtime",
"category": "task_lifecycle",
"level": "info",
"operation": "task.complete",
"status": "completed",
"duration_ms": 8420,
"workflow_id": "33333333-3333-3333-3333-333333333333",
"task_id": "44444444-4444-4444-4444-444444444444",
"work_item_id": "55555555-5555-5555-5555-555555555555",
"stage_name": "Review",
"activation_id": "66666666-6666-6666-6666-666666666666",
"is_orchestrator_task": false,
"execution_backend": "runtime_plus_task",
"tool_owner": "task",
"role": "reviewer",
"payload": {
"summary": "Task completed"
}
}
]
}
FieldContractMeaning
trace_id / span_id / parent_span_idUUIDDistributed tracing identifiers that tie related runtime activity together.
sourceenumWhich subsystem emitted the row, such as runtime, platform, or task_container.
categoryenumCoarse log family such as llm, tool, task_lifecycle, or auth.
levelenumLog severity.
operationstringStable event or action name, for example task.complete.
statusenumOutcome class for the operation, such as started, completed, or failed.
duration_msinteger or nullOperation duration when timing is known.
payloadarbitrary JSON objectStructured event body for normal log detail.
errorstructured object or nullStructured error body when the event failed.
linkage idsUUID / stringworkspace_id, workflow_id, task_id, work_item_id, activation_id, and stage_name attach the log to the workflow graph.
execution fieldsenum / boolean / stringis_orchestrator_task, execution_backend, tool_owner, and role explain where in the execution model the event came from.
actor fieldsstringactor_type, actor_id, and actor_name identify who performed the action when known.
resource fieldsstringresource_type, resource_id, and resource_name point at the affected external resource when relevant.
{
"data": {
"inserted": 1
}
}

GET /api/v1/logs

Scope: agent

  • workspace_id
  • workflow_id
  • task_id
  • work_item_id
  • stage_name
  • activation_id
  • source
  • category
  • level
  • operation
  • status
  • role
  • trace_id
  • since
  • until
  • search
  • detail=summary
  • cursor
  • per_page
{
"data": [
{
"id": "77777777-7777-7777-7777-777777777777",
"created_at": "2026-03-31T19:10:00.000Z",
"source": "runtime",
"category": "task_lifecycle",
"level": "info",
"operation": "task.complete",
"status": "completed",
"duration_ms": 8420,
"workflow_id": "33333333-3333-3333-3333-333333333333",
"task_id": "44444444-4444-4444-4444-444444444444",
"work_item_id": "55555555-5555-5555-5555-555555555555",
"stage_name": "Review",
"activation_id": "66666666-6666-6666-6666-666666666666",
"is_orchestrator_task": false,
"execution_backend": "runtime_plus_task",
"tool_owner": "task",
"actor_type": "agent",
"actor_id": "99999999-9999-9999-9999-999999999999",
"trace_id": "11111111-1111-1111-1111-111111111111",
"span_id": "22222222-2222-2222-2222-222222222222",
"error": null,
"payload": {
"summary": "Task completed"
}
}
],
"meta": {
"next_cursor": "opaque-cursor"
}
}

When detail=summary, the API strips payload and reduces error to a lighter summary form.

FieldContractMeaning
idserver-generatedStable log row id for later lookup and export.
created_atserver-generatedServer-side event timestamp.
payloadarbitrary JSON objectFull structured event body unless summary mode strips it.
errorstructured object or nullStructured error payload when present.
next_cursoropaqueOpaque keyset pagination cursor used to fetch the next window of results.

GET /api/v1/logs/:id

Scope: agent

Success response:

{
"data": {
"id": "77777777-7777-7777-7777-777777777777",
"operation": "task.complete"
}
}

If missing, the route returns:

{
"error": "Not found"
}

GET /api/v1/logs/stream

Scope: agent

This route returns text/event-stream.

event: log
data: {"id":"77777777-7777-7777-7777-777777777777","operation":"task.complete","status":"completed"}
event: heartbeat
data: {"ts":"2026-03-31T19:10:00.000Z"}

The stream accepts the same major filter fields as the query route.

The stream sends fully materialized public log rows, so the event data shape matches the normal single-row query shape rather than a reduced stream-specific schema.

GET /api/v1/logs/export

Scope: operator role

  • all major log filters
  • format=json or format=csv
  • order=asc|desc

The route streams the export body directly and sets:

  • Content-Type: application/json or text/csv
  • Content-Disposition: attachment; filename="logs-YYYY-MM-DD.ext"

GET /api/v1/logs/stats

Scope: agent

Key query:

  • group_by

Supported groups in current code:

  • category
  • operation
  • level
  • task_id
  • work_item_id
  • stage_name
  • activation_id
  • is_orchestrator_task
  • source
  • execution_backend
  • tool_owner
  • GET /api/v1/logs/operations
  • GET /api/v1/logs/roles
  • GET /api/v1/logs/actors
  • GET /api/v1/logs/workflows

These are not just internal dashboard conveniences. They are useful for building stable external filter UIs without scanning the full log corpus first.

The broader event system also exposes:

  • GET /api/v1/events
  • GET /api/v1/events/stream

Those routes operate at the workflow and entity-event layer, while /api/v1/logs... operates at execution-log granularity.