Sinks
Sinks define where agent output goes after a run completes. They are most useful in daemon mode and flow pipelines, where agents run unattended and their results need to be routed somewhere — a webhook, a file, a custom function, or another agent.
Sinks are configured in the spec.sinks list.
Quick Example
spec:
sinks:
- type: webhook
url: https://hooks.slack.com/services/T.../B.../xxx
headers:
Content-Type: application/json
- type: file
path: ./output/results.json
format: jsonSink Types
| Type | Description |
|---|---|
webhook | HTTP POST to a URL |
file | Write to a local file |
custom | Call a Python function |
Webhook
Sends a JSON payload to a URL via HTTP POST. Useful for Slack, Discord, PagerDuty, or any HTTP endpoint.
sinks:
- type: webhook
url: https://hooks.slack.com/services/T.../B.../xxx
headers:
Content-Type: application/json
Authorization: Bearer ${WEBHOOK_TOKEN}
timeout_seconds: 30
retry_count: 3| Field | Type | Default | Description |
|---|---|---|---|
url | str | (required) | Destination URL |
method | str | "POST" | HTTP method |
headers | dict | {} | HTTP headers (supports ${VAR} substitution) |
timeout_seconds | int | 30 | Request timeout |
retry_count | int | 0 | Number of retry attempts on failure |
Payload Format
The webhook POST body is a JSON object:
{
"agent_name": "monitor-agent",
"run_id": "a1b2c3d4e5f6",
"trigger_type": "cron",
"status": "success",
"output": "All 3 services healthy. Response times: api=120ms, web=85ms, db=45ms.",
"timestamp": "2025-01-15T09:00:05Z",
"tokens_used": 1250,
"duration_ms": 4200
}File
Writes agent output to a local file. Supports JSON and plain text formats.
sinks:
- type: file
path: ./output/results.json
format: json| Field | Type | Default | Description |
|---|---|---|---|
path | str | (required) | Output file path |
format | str | "json" | Output format: "json" or "text" |
json— writes a JSON object (same schema as webhook payload)text— writes the raw output string
Custom
Calls a Python function with the run result. Use this for custom integrations — database writes, email, message queues, or anything else.
sinks:
- type: custom
module: my_sinks
function: send_to_database| Field | Type | Default | Description |
|---|---|---|---|
module | str | (required) | Python module path (must be importable) |
function | str | (required) | Function name to call |
The function signature:
def send_to_database(result: dict) -> None:
"""Called by InitRunner after each agent run.
Args:
result: Run result dict (same schema as webhook payload).
"""
# ... process resultMultiple Sinks
An agent can have multiple sinks. All sinks fire after each run completes:
spec:
sinks:
# Log to file
- type: file
path: ./logs/runs.json
format: json
# Notify Slack
- type: webhook
url: ${SLACK_WEBHOOK_URL}
# Store in database
- type: custom
module: my_sinks
function: store_resultSinks with Daemon Mode
Sinks are most commonly used with triggers and daemon mode. When a trigger fires and an agent run completes, all configured sinks receive the result:
spec:
triggers:
- type: cron
schedule: "0 */6 * * *"
prompt: "Check system health and report status."
sinks:
- type: webhook
url: ${SLACK_WEBHOOK_URL}
- type: file
path: ./logs/health-checks.json
format: jsoninitrunner run role.yaml --daemonEvery 6 hours, the agent runs, and the output is sent to both Slack and the log file.
Sinks with Flow
In flow pipelines, agent chaining is handled by the flow orchestration layer. See the flow documentation for multi-agent pipeline examples.