# HTTP Callbacks Guide

A comprehensive guide to using HTTP callbacks for real-time event streaming in AriaFlow.

## Overview

HTTP callbacks enable your AriaFlow agents to stream events (text tokens, tool calls, handoffs, etc.) to external webhooks in real-time. This is essential for:
- Real-time analytics and monitoring
- Live UI updates
- Audit logging and compliance
- Integration with external systems (Dash7, monitoring platforms, etc.)

## Quick Start

### 1. Add Callback to Configuration

Add a `callback` block to your `ariaflow.jsonc`:

```jsonc
{
  "name": "my-agent",
  "runtime": {
    "defaultAgent": "support"
  },
  "callback": {
    "url": "https://your-webhook.com/events",
    "method": "POST"
  }
}
```

### 2. Run Your Agent

That's it! Events will now be streamed to your webhook in real-time.

## Configuration Reference

### Basic Options

```jsonc
{
  "callback": {
    "url": "https://webhook.example.com/events",
    "method": "POST"
  }
}
```

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `url` | string | Required | Webhook endpoint URL |
| `method` | string | `"POST"` | HTTP method (`POST` or `PUT`) |

### Headers

```jsonc
{
  "callback": {
    "url": "https://webhook.example.com/events",
    "headers": {
      "Authorization": "Bearer $ENV.API_KEY",
      "Content-Type": "application/json",
      "X-Custom-Header": "custom-value"
    }
  }
}
```

Headers support environment variables:
- `$ENV.VAR_NAME` - Direct substitution
- `${ENV.VAR_NAME}` - Bracket syntax

### Event Filtering

Control which events are sent using `allowList` and `denyList`:

```jsonc
{
  "callback": {
    "url": "https://webhook.example.com/events",
    "allowList": ["text-delta", "tool-call", "tool-result"],
    "denyList": ["step-start", "step-end"]
  }
}
```

**Filtering Rules:**
1. `denyList` takes precedence over `allowList`
2. If `allowList` is empty, all non-denied events are sent
3. If `allowList` is non-empty, only those events are sent (unless denied)

### Available Event Types

| Event Type | Description |
|------------|-------------|
| `text-delta` | Text token as it streams |
| `tool-call` | Tool invocation starts |
| `tool-result` | Tool returns data |
| `tool-error` | Tool fails |
| `tool-start` | Tool begins (with filler) |
| `tool-done` | Tool completes |
| `handoff` | Agent handoff occurs |
| `agent-start` | Agent starts |
| `agent-end` | Agent completes |
| `step-start` | Step begins |
| `step-end` | Step completes |
| `node-enter` | Flow node entered |
| `node-exit` | Flow node exited |
| `flow-transition` | Flow transitions |
| `flow-end` | Flow completes |
| `error` | Error occurs |
| `done` | Session completes |

### Full Text Accumulation

When `includeFullText: true`, each payload includes accumulated text:

```jsonc
{
  "callback": {
    "url": "https://webhook.example.com/events",
    "includeFullText": true
  }
}
```

**Example Payload:**
```json
{
  "sessionId": "550e8400-e29b-41d4-a716-446655440000",
  "agentId": "support",
  "timestamp": "2026-02-01T17:00:00.000Z",
  "part": {
    "type": "text-delta",
    "text": "Hello"
  },
  "fullText": "Hello! How can I assist you today?"
}
```

The `fullText` field accumulates all `text-delta` events for the current turn and is cleared at `turn-end`.

## Complete Example

```jsonc
{
  "$schema": "https://mithushancj.com/config.json",
  "name": "support-agent",
  "version": "1.0.0",
  "runtime": {
    "defaultAgent": "support",
    "defaultModel": "default"
  },
  "models": {
    "default": "openai:gpt-4o-mini"
  },
  "callback": {
    "url": "https://analytics.example.com/ariaflow-events",
    "method": "POST",
    "headers": {
      "Authorization": "Bearer $ENV.ANALYTICS_API_KEY",
      "X-Source": "production",
      "X-Environment": "production"
    },
    "allowList": ["text-delta", "tool-call", "tool-result", "handoff", "error"],
    "includeFullText": true
  },
  "agents": {
    "support": {
      "type": "llm",
      "description": "Customer support agent",
      "prompt": "You are a helpful customer support agent.",
      "tools": ["search", "create_ticket"]
    }
  },
  "tools": {
    "search": {
      "type": "module",
      "entry": "./tools/search/index.ts"
    },
    "create_ticket": {
      "type": "module",
      "entry": "./tools/create_ticket/index.ts"
    }
  }
}
```

## Code-First Usage

For programmatic control, configure callbacks in code:

```typescript
import { Runtime, type AgentConfig, type HttpCallbackConfig } from '@ariaflowagents/core';
import { openai } from '@ai-sdk/openai';

const callbackConfig: HttpCallbackConfig = {
  url: 'https://webhook.example.com/events',
  method: 'POST',
  headers: {
    'Authorization': 'Bearer $ENV.API_KEY',
    'X-Source': 'code-first-agent'
  },
  allowList: ['text-delta', 'tool-call'],
  includeFullText: true
};

const runtime = new Runtime({
  agents: [agent],
  defaultAgentId: 'support',
  callback: callbackConfig
});
```

## Security Best Practices

1. **Never commit API keys**: Always use environment variables
2. **Validate webhooks**: Verify signatures at the receiving end
3. **Use HTTPS**: Always use secure endpoints in production
4. **Sanitize headers**: Avoid logging sensitive header values
5. **Implement timeouts**: Configure reasonable timeouts on the webhook server

## Performance Considerations

The HTTP callback uses a **fire-and-forget** pattern to ensure the agent's main stream is not blocked.

### What This Means

- HTTP requests are sent without awaiting the response
- Failed requests log to console but don't affect the agent
- The agent continues processing even if the webhook is slow

### Recommendations

1. **Keep webhooks fast**: Response time should be < 100ms
2. **Use async processing**: Process events asynchronously on the receiver side
3. **Implement batching**: Consider batching events if volume is high
4. **Monitor failures**: Watch logs for failed webhook deliveries
5. **Consider message queues**: For critical events, use a queue instead of direct webhooks

## Debugging

### Enable Debug Logging

Set the `ARIAFLOW_DEBUG` environment variable to see callback activity:

```bash
ARIAFLOW_DEBUG=callback bun run run.ts
```

### Common Issues

**Events not received:**
- Verify webhook URL is correct and accessible
- Check firewall/network settings
- Ensure `allowList`/`denyList` aren't filtering all events

**Partial events:**
- Check `allowList` includes the expected event types
- Verify `denyList` isn't blocking events

**Missing fullText:**
- Ensure `includeFullText: true` is set
- Note: `fullText` is cleared at `turn-end`

## Integration Examples

### Receiving Events in Node.js

```javascript
const http = require('http');

const server = http.createServer((req, res) => {
  let body = '';
  
  req.on('data', chunk => {
    body += chunk.toString();
  });
  
  req.on('end', () => {
    try {
      const event = JSON.parse(body);
      console.log(`Received ${event.part.type} event`);
      console.log('Full text:', event.fullText);
    } catch (error) {
      console.error('Failed to parse event:', error);
    }
    
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ success: true }));
  });
});

server.listen(8765, () => {
  console.log('Webhook server listening on port 8765');
});
```

### Sending to Multiple Endpoints

Use multiple agents or extend the configuration to support multiple callbacks:

```typescript
import { Runtime, createHttpCallback } from '@ariaflowagents/core';

const analyticsCallback = createHttpCallback({
  url: 'https://analytics.example.com/events',
  allowList: ['text-delta', 'tool-call']
});

const auditCallback = createHttpCallback({
  url: 'https://audit.example.com/events',
  allowList: ['tool-call', 'tool-result', 'handoff', 'error']
});

const runtime = new Runtime({
  agents: [agent],
  defaultAgentId: 'support',
  hooks: {
    onStreamPart: async (context, part) => {
      await analyticsCallback(context, part);
      await auditCallback(context, part);
    }
  }
});
```

## See Also

- [Config Guide README](./README.md) - General configuration documentation
- [Core Callbacks](../ariaflow-core/src/callbacks/README.md) - Core callback utilities
- [Examples](../examples/http-callback-demo/) - Working callback examples
