Configure A2A-ACP using environment variables for simple, secure, and flexible setup.
| Variable | Description | Example |
|---|---|---|
A2A_AGENT_COMMAND |
Path to Zed ACP agent binary | /usr/local/bin/codex-acp |
A2A_AUTH_TOKEN |
Authentication token for A2A-ACP | your-secret-token |
| Variable | Description | Example |
|---|---|---|
A2A_AGENT_API_KEY |
API key for agent authentication | ${OPENAI_API_KEY} or ${GEMINI_API_KEY} (supports apikey, gemini-api-key, codex-api-key, openai-api-key) |
A2A_AGENT_DESCRIPTION |
Human-readable agent description | OpenAI Codex for A2A-ACP or Gemini CLI for A2A-ACP |
| Variable | Description | Default |
|---|---|---|
HOST |
Server bind address | 0.0.0.0 |
PORT |
Server port | 8000 |
LOG_LEVEL |
Logging level | INFO |
A2A-ACP supports multiple Zed ACP-compliant agents:
| Agent | Authentication Method | Environment Variable | Description |
|---|---|---|---|
codex-acp |
apikey, codex-api-key, openai-api-key |
${OPENAI_API_KEY} |
OpenAI Codex agent |
claude-code-acp |
apikey |
${ANTHROPIC_API_KEY} |
Anthropic Claude agent |
gemini-cli |
gemini-api-key |
${GEMINI_API_KEY} |
Google Gemini agent |
The server automatically detects the authentication method based on the agent's capabilities and uses the appropriate API key.
cp .env.example .env# Open .env and configure for OpenAI Codex:
A2A_AGENT_COMMAND="/usr/local/bin/codex-acp"
A2A_AGENT_API_KEY="${OPENAI_API_KEY}"
A2A_AGENT_DESCRIPTION="OpenAI Codex for A2A-ACP"
A2A_AUTH_TOKEN="your-secure-secret-token"
# Or for Gemini CLI:
A2A_AGENT_COMMAND="/opt/homebrew/bin/gemini --experimental-acp"
A2A_AGENT_API_KEY="${GEMINI_API_KEY}"
A2A_AGENT_DESCRIPTION="Gemini CLI for A2A-ACP"
A2A_AUTH_TOKEN="your-secure-secret-token"# Load the environment file
source .env
# Or use a tool like direnv:
# echo 'source .env' >> .envrc
# direnv allowversion: '3.8'
services:
a2a-acp:
build: .
ports:
- "8000:8000"
environment:
- A2A_AGENT_COMMAND=/usr/local/bin/codex-acp
- A2A_AGENT_API_KEY=${OPENAI_API_KEY}
- A2A_AUTH_TOKEN=${A2A_AUTH_TOKEN}
- LOG_LEVEL=INFO
restart: unless-stopped
# Alternative configuration for Gemini CLI
# a2a-acp-gemini:
# build: .
# ports:
# - "8000:8000"
# environment:
# - A2A_AGENT_COMMAND=/opt/homebrew/bin/gemini --experimental-acp
# - A2A_AGENT_API_KEY=${GEMINI_API_KEY}
# - A2A_AUTH_TOKEN=${A2A_AUTH_TOKEN}
# - LOG_LEVEL=INFO
# restart: unless-stopped# For OpenAI Codex
docker run -d \
--name a2a-acp-codex \
-p 8000:8000 \
-e A2A_AGENT_COMMAND="/usr/local/bin/codex-acp" \
-e A2A_AGENT_API_KEY="${OPENAI_API_KEY}" \
-e A2A_AUTH_TOKEN="your-secret-token" \
-e LOG_LEVEL=INFO \
your-registry/a2a-acp:latest
# For Gemini CLI
docker run -d \
--name a2a-acp-gemini \
-p 8001:8000 \
-e A2A_AGENT_COMMAND="/opt/homebrew/bin/gemini --experimental-acp" \
-e A2A_AGENT_API_KEY="${GEMINI_API_KEY}" \
-e A2A_AUTH_TOKEN="your-secret-token" \
-e LOG_LEVEL=INFO \
your-registry/a2a-acp:latestConfigure push notifications for real-time task monitoring:
# Enable push notifications
export PUSH_NOTIFICATIONS_ENABLED=true
# Webhook timeout (seconds)
export PUSH_NOTIFICATION_WEBHOOK_TIMEOUT=30
# Retry attempts for failed webhooks
export PUSH_NOTIFICATION_RETRY_ATTEMPTS=3
# HMAC secret for webhook signature verification
export PUSH_NOTIFICATION_HMAC_SECRET="your-hmac-secret"# Database file location
export DATABASE_URL="sqlite:///data/a2a_acp.db"
# Connection pool settings
export DB_POOL_SIZE=10
export DB_MAX_OVERFLOW=20# Task cleanup interval (seconds)
export TASK_CLEANUP_INTERVAL=3600
# Maximum concurrent tasks
export MAX_CONCURRENT_TASKS=100
# Task timeout (seconds)
export TASK_TIMEOUT=300# Maximum request size (MB)
export MAX_REQUEST_SIZE_MB=10
# CORS origins (comma-separated)
export CORS_ORIGINS="https://your-domain.com,https://app.your-domain.com"Configure policy-driven auto-approvals and governor pipelines through YAML files. Both files are optional; if omitted no automatic decisions or external governors are executed.
# Override default locations
export A2A_GOVERNORS_FILE="config/governors.yaml"
export A2A_AUTO_APPROVAL_FILE="config/auto_approval_policies.yaml"permission_governors:
- id: security-diff-check
type: script
command: ["python3", "governors/security.py"]
timeout_ms: 5000
output_governors:
- id: code-reviewer
type: http
url: https://governor.example.com/review
headers:
Authorization: Bearer ${GOVERNOR_TOKEN}
permission_settings:
stop_on_first_reject: true
auto_decision: all_approve
output_settings:
max_iterations: 3Policy decisions accept either the legacy option IDs (allow, approved, deny) or the Gemini-native values (proceed_once, proceed_always, cancel). The resolver automatically maps synonyms to the closest option exposed by the agent, so the example below works even when Gemini presents its custom option list.
auto_approval_policies:
- id: docs-edits
applies_to:
- "functions.acp_fs__write_text_file"
- "functions.acp_fs__edit_text_file"
include_paths:
- "*.md"
- "docs/**"
decision:
type: approve
optionId: proceed_once # maps to the agent's one-time allow option
reason: "Documentation edits auto-approved"
skipGovernors: true
- id: safe-shell
applies_to: ["functions.shell"]
parameters:
command_prefix: ["git", "status"]
decision:
type: approve
optionId: allow # automatically resolves to proceed_once/allow_alwaysNote: Rejection aliases are handled the same way. Returning
deny,reject,abort, orcancelwill select the first reject-style option offered by the agent.
Enable support for the A2A development-tool extension, which provides structured tool interactions including slash commands, tool call lifecycles, user confirmations, and agent thoughts. This extension enhances interoperability with clients like Gemini CLI.
| Variable | Description | Default |
|---|---|---|
DEVELOPMENT_TOOL_EXTENSION_ENABLED |
Enable the development-tool extension in agent capabilities, endpoints, and metadata emission | True |
Set the environment variable to activate extension features:
export DEVELOPMENT_TOOL_EXTENSION_ENABLED=trueWith the extension enabled:
- Agent card includes the extension URI in
capabilities.extensions. - Bash tools from
tools.yamlare automatically exposed as slash commands via/a2a/commands/get. - Task updates include
DevelopmentToolEventmetadata for tool lifecycles. - New endpoints
/a2a/commands/getand/a2a/command/executebecome available.
No additional config needed beyond enabling the flag. Existing tools.yaml files map directly:
# tools.yaml (example)
tools:
web_request:
name: "HTTP Request"
description: "Execute HTTP requests via curl"
script: |
#!/bin/bash
curl -X {{method}} "{{url}}" -w "STATUS:%{http_code}\n"
parameters:
- name: method
type: string
required: true
- name: url
type: string
required: true
sandbox:
requires_confirmation: false # No confirmation for this tool
timeout: 30This tool becomes available as the /web_request slash command.
For sensitive tools, enable confirmations in tools.yaml:
tools:
database_query:
name: "Database Query"
description: "Execute SQL queries"
script: |
#!/bin/bash
psql -d {{database}} -c "{{query}}"
parameters:
- name: database
type: string
required: true
- name: query
type: string
required: true
sandbox:
requires_confirmation: true
confirmation_message: "Execute SQL query on production database? This may modify data."
timeout: 10Workflow:
- Client executes
/database_queryvia/a2a/command/execute. - Task enters PENDING;
input_requiredevent withConfirmationRequest. - User approves via
tasks/provideInputAndContinue. - Tool executes; SUCCEEDED with
ToolOutput(stdout).
Extension metadata can include agent thoughts for transparency. Configure in tool or globally via settings.
To disable for legacy compatibility or reduced features:
export DEVELOPMENT_TOOL_EXTENSION_ENABLED=falseEffects:
- Extension URI removed from agent card.
/a2a/commands/*endpoints return 404.- Tool calls use legacy flows without
DevelopmentToolEventmetadata. - Existing bash execution and confirmations continue via
input_requiredevents.
When to Disable:
- Interacting with pre-v0.3.0 A2A clients that ignore unknown metadata.
- Reducing endpoint surface for security audits.
- Testing without extension overhead.
- Enable for Modern Clients: Use with Gemini CLI or extension-aware UIs for rich interactions.
- Security: Confirmation-enabled tools prevent unauthorized executions; always review
allowed_commandsin sandbox. - Performance: Extension adds minimal overhead (~5% latency for metadata serialization).
- Migration: Existing
tools.yamlworks unchanged; enable flag to activate slash commands. - Version Compatibility: Supports development-tool v1.0.0; update URI in future for v2+.
For full implementation details, see DEVELOPMENT_TOOL_EXTENSION.md.
# Check system health
curl -X GET "http://localhost:8000/health" \
-H "Authorization: Bearer your-token"
# Response includes:
# - Overall system status
# - Component health (database, push notifications)
# - Version information# Get push notification metrics
curl -X GET "http://localhost:8000/metrics/push-notifications" \
-H "Authorization: Bearer your-token"
# Get system metrics
curl -X GET "http://localhost:8000/metrics/system" \
-H "Authorization: Bearer your-token"# Check if configuration is valid
python -c "
import os
from src.a2a_acp.settings import Settings
try:
settings = Settings()
print('✅ Configuration is valid')
print(f'Agent: {settings.agent_description}')
print(f'Auth: {"Enabled" if settings.auth_token else "Disabled"}')
except Exception as e:
print(f'❌ Configuration error: {e}')
"# Verify all required environment variables are set
python -c "
import os
required = ['A2A_AGENT_COMMAND', 'A2A_AUTH_TOKEN']
missing = [var for var in required if not os.getenv(var)]
if missing:
print(f'❌ Missing required variables: {missing}')
else:
print('✅ All required variables are set')
""Agent command not found"
# Check if agent binary exists and is executable
ls -la $(which codex-acp)
# or
which codex-acp"Authentication failed"
# Verify auth token is set correctly
echo "Auth token: $A2A_AUTH_TOKEN"
# Test health endpoint with authentication
curl -H "Authorization: Bearer $A2A_AUTH_TOKEN" \
http://localhost:8000/health"Database connection failed"
# Check database file permissions
ls -la data/a2a_acp.db
# Verify SQLite is available
sqlite3 --version- Use strong, randomly generated tokens
- Rotate tokens regularly (monthly recommended)
- Use different tokens for different environments
- Never commit
.envfiles to version control - Use
.env.exampleas a template - Consider using secret management systems (Vault, etc.)
- Run behind reverse proxy with TLS termination
- Use internal network for inter-service communication
- Implement rate limiting and DDoS protection
Configuration complete! 🔧 Next: Quick Start Tutorial