Introduction
In this tutorial, we'll explore how to set up and use Claude Code's new Channels feature to create always-on AI agents that can respond to external events like CI pipeline results or chat messages. This capability transforms Claude from a simple code assistant into a proactive agent that can monitor and react to system events automatically.
Channels allow Claude to maintain an active session and receive real-time updates, making it perfect for automation tasks, monitoring systems, or collaborative coding environments where you want AI assistance to be constantly available.
Prerequisites
To follow this tutorial, you'll need:
- An Anthropic API key with Claude Code access
- Python 3.8 or higher installed
- Basic understanding of REST APIs and webhooks
- Access to a CI/CD system (like GitHub Actions or GitLab CI) or a chat system
- Some familiarity with HTTP requests and JSON handling
Step-by-Step Instructions
1. Set Up Your Anthropic API Environment
First, we need to configure our environment with the Anthropic API key and install required dependencies.
import os
from anthropic import Anthropic
# Set your API key
ANTHROPIC_API_KEY = os.getenv('ANTHROPIC_API_KEY')
client = Anthropic(api_key=ANTHROPIC_API_KEY)
Why: This establishes our connection to Anthropic's API, which is necessary to interact with Claude Code and create channels.
2. Create a Basic Claude Code Session
Before setting up channels, we need to create a Claude Code session that will serve as our agent's base.
def create_claude_session():
response = client.messages.create(
model="claude-3-opus-20240229",
max_tokens=1000,
messages=[
{
"role": "user",
"content": "You are an AI coding assistant. You will receive events and messages to process. Respond concisely and help with code tasks."
}
]
)
return response
Why: This creates a persistent conversation context where Claude can process incoming events and maintain state across multiple interactions.
3. Implement Channel Creation
Now we'll create the core functionality for setting up channels that can receive external events.
import requests
import json
# Function to create a channel
def create_channel(session_id, channel_name):
channel_data = {
"session_id": session_id,
"channel_name": channel_name,
"event_types": ["ci_result", "chat_message", "error_log"],
"webhook_url": "https://your-server.com/webhook"
}
response = requests.post(
"https://api.anthropic.com/v1/channels",
headers={
"Authorization": f"Bearer {ANTHROPIC_API_KEY}",
"Content-Type": "application/json"
},
json=channel_data
)
return response.json()
Why: Channels act as communication pathways that allow external systems to push events directly to Claude, enabling automated responses without manual intervention.
4. Set Up Webhook Endpoint
We need to create an endpoint that can receive events from external systems and forward them to Claude.
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def handle_webhook():
event_data = request.json
# Process the event and send to Claude
try:
# Extract relevant information from the event
event_type = event_data.get('type')
payload = event_data.get('payload')
# Forward to Claude Code
Claude Code response = client.messages.create(
model="claude-3-opus-20240229",
max_tokens=1000,
messages=[
{
"role": "user",
"content": f"Received {event_type}: {json.dumps(payload)}"
}
]
)
return jsonify({"status": "processed", "response": response.content[0].text})
except Exception as e:
return jsonify({"status": "error", "message": str(e)}), 500
Why: The webhook endpoint acts as the bridge between external systems and Claude, allowing real-time event processing and automated responses.
5. Configure CI Integration
Let's set up a sample CI integration that sends results to our Claude agent:
def send_ci_result_to_claude(ci_result):
webhook_url = "https://your-server.com/webhook"
payload = {
"type": "ci_result",
"payload": {
"build_id": ci_result.get('build_id'),
"status": ci_result.get('status'),
"timestamp": ci_result.get('timestamp'),
"url": ci_result.get('url'),
"message": ci_result.get('message')
}
}
response = requests.post(webhook_url, json=payload)
return response.status_code
Why: This demonstrates how CI results can be automatically sent to Claude, enabling it to analyze build outcomes and provide insights or recommendations.
6. Test Your Channel Setup
Let's run a test to verify everything is working correctly:
def test_channel_setup():
# Create a session
session = create_claude_session()
session_id = session.id
# Create a channel
channel = create_channel(session_id, "ci-monitoring")
print(f"Channel created: {channel}")
# Test sending a CI result
test_ci_result = {
"build_id": "build-123",
"status": "success",
"timestamp": "2024-01-01T00:00:00Z",
"url": "https://ci.example.com/build/123",
"message": "All tests passed successfully"
}
status = send_ci_result_to_claude(test_ci_result)
print(f"CI result sent with status: {status}")
# Run the test
if __name__ == "__main__":
test_channel_setup()
Why: This comprehensive test verifies that all components work together, from session creation to event forwarding to Claude processing.
Summary
In this tutorial, we've built a foundation for creating always-on AI agents using Claude Code's Channels feature. We've learned how to:
- Set up Claude Code sessions for persistent interaction
- Create channels that can receive external events
- Implement webhook endpoints to process incoming data
- Integrate with CI/CD systems to automatically send build results
This setup allows Claude to function as a proactive agent that monitors systems and responds to events without human intervention. The channels feature transforms Claude from a reactive assistant into an always-on system that can monitor and react to external events in real-time, making it ideal for automation, monitoring, and collaborative development environments.



