Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
99248df
add typed message protocol with pydantic discriminated unions
0xSY3 Apr 3, 2026
1e5e50f
add session tracking and task state machine
0xSY3 Apr 3, 2026
0501ded
implement parallel fan-out and coordinator orchestration
0xSY3 Apr 4, 2026
a23f425
replace webhook polling with threading.Event, wire sessions and signa…
0xSY3 Apr 4, 2026
bdaa95a
export orchestration API, add openai and pytest-asyncio deps
0xSY3 Apr 5, 2026
042eb19
add tests for typed messages, signatures, sessions, orchestration
0xSY3 Apr 5, 2026
2d5c1a5
add orchestration examples and AAPL stock research demo
0xSY3 Apr 6, 2026
274ec5f
use real Yahoo Finance data in stock research demo
0xSY3 Apr 6, 2026
ead853d
Merge remote-tracking branch 'origin/main' into feat/multi-agent-orch…
0xSY3 Apr 10, 2026
d079df9
feat: add services directory support on top of ZyndService refactor
0xSY3 Apr 10, 2026
500161b
feat: services directory — search, call, use services via orchestrator
0xSY3 Apr 10, 2026
2fed72a
feat: dynamic service tool generation for LLM agents
0xSY3 Apr 10, 2026
fedc460
align field names with agentdns api renames
0xSY3 Apr 17, 2026
47b4d35
merge main into feat/multi-agent-orchestration
0xSY3 Apr 17, 2026
85cfc90
fix get_entity_fqan - search results use agent_id not entity_id
0xSY3 Apr 17, 2026
c113eb7
fix: broken search_agents refs, register argparse, duplicate except
0xSY3 Apr 17, 2026
f3f9432
fix: keypair env var, dead imports, sender_id, mutable default
0xSY3 Apr 17, 2026
12c1520
cleanup: logger over print, no config mutation, better error msgs, ti…
0xSY3 Apr 17, 2026
2702689
Merge remote-tracking branch 'origin/main' into feat/multi-agent-orch…
0xSY3 Apr 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# CLAUDE.md

<!-- autoskills:start -->

Summary generated by `autoskills`. Check the full files inside `.claude/skills`.

## Accessibility (a11y)

Audit and improve web accessibility following WCAG 2.2 guidelines. Use when asked to "improve accessibility", "a11y audit", "WCAG compliance", "screen reader support", "keyboard navigation", or "make accessible".

- `.claude/skills/accessibility/SKILL.md`
- `.claude/skills/accessibility/references/A11Y-PATTERNS.md`: Practical, copy-paste-ready patterns for common accessibility requirements. Each pattern is self-contained and linked from the main [SKILL.md](../SKILL.md).
- `.claude/skills/accessibility/references/WCAG.md`

## Flask API Development

>

- `.claude/skills/flask-api-development/SKILL.md`
- `.claude/skills/flask-api-development/references/application-factory-and-configuration.md`
- `.claude/skills/flask-api-development/references/authentication-and-jwt.md`
- `.claude/skills/flask-api-development/references/blueprints-for-modular-api-design.md`
- `.claude/skills/flask-api-development/references/database-models-with-sqlalchemy.md`
- `.claude/skills/flask-api-development/references/flask-application-setup.md`
- `.claude/skills/flask-api-development/references/request-validation.md`

## Design Thinking

Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beaut...

- `.claude/skills/frontend-design/SKILL.md`

## Pydantic Validation Skill

Python data validation using type hints and runtime type checking with Pydantic v2's Rust-powered core for high-performance validation in FastAPI, Django, and configuration management.

- `.claude/skills/pydantic/SKILL.md`

## Python Code Executor

Execute Python code in a safe sandboxed environment via [inference.sh](https://inference.sh). Pre-installed: NumPy, Pandas, Matplotlib, requests, BeautifulSoup, Selenium, Playwright, MoviePy, Pillow, OpenCV, trimesh, and 100+ more libraries. Use for: data processing, web scraping, image manipulat...

- `.claude/skills/python-executor/SKILL.md`

## Python Development Patterns

Pythonic idioms, PEP 8 standards, type hints, and best practices for building robust, efficient, and maintainable Python applications.

- `.claude/skills/python-patterns/SKILL.md`

## Python Testing Patterns

Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development. Use when writing Python tests, setting up test suites, or implementing testing best practices.

- `.claude/skills/python-testing-patterns/SKILL.md`
- `.claude/skills/python-testing-patterns/references/advanced-patterns.md`: Advanced testing patterns including async code, monkeypatching, temporary files, conftest setup, property-based testing, database testing, CI/CD integration, and configuration.

## SEO optimization

Optimize for search engine visibility and ranking. Use when asked to "improve SEO", "optimize for search", "fix meta tags", "add structured data", "sitemap optimization", or "search engine optimization".

- `.claude/skills/seo/SKILL.md`

<!-- autoskills:end -->
240 changes: 240 additions & 0 deletions DEPLOYMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
# Deployment Guide

This guide covers deploying ZyndAI agents to production, including configuration for proxies, timeouts, and AG-UI streaming.

## Proxy Configuration

When deploying agents behind a reverse proxy (nginx, Apache, etc.), ensure your proxy is configured to support AG-UI streaming with proper timeout settings.

### Nginx Configuration Example

```nginx
upstream agent_backend {
server localhost:5000;
}

server {
listen 80;
server_name agent.example.com;

location / {
proxy_pass http://agent_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

# Important: Disable buffering for SSE streaming
proxy_buffering off;
proxy_cache off;

# Set proper timeouts for long-lived streams
# proxy_connect_timeout: Time to establish connection (default: 60s)
proxy_connect_timeout 60s;

# proxy_read_timeout: Time waiting for response data (default: 60s)
# CRITICAL for AG-UI streams: Set to match or exceed stream timeout
# If streams are configured with timeout=300s, set this to at least 300s
proxy_read_timeout 600s; # 10 minutes

# proxy_send_timeout: Time waiting for client to accept data
proxy_send_timeout 60s;

# Pass through important headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```

### Apache Configuration Example

```apache
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://localhost:5000/
ProxyPassReverse / http://localhost:5000/

# Configure timeout for SSE streams
# Important: Match or exceed the stream timeout setting
ProxyTimeout 600 # 10 minutes
TimeOut 600 # Connection timeout

# Disable buffering for real-time events
SetEnv proxy-nokeepalive 1
SetEnv proxy-initial-handler default
```

## Stream Timeout Configuration

AG-UI streams are configured with a default timeout of 5 minutes (300 seconds). This timeout is:

1. **Set on the SDK side** (`zyndai_agent/ui/sse.py`): Streams remain open for the configured duration before closing
2. **Enforced on the proxy side**: The proxy must have a read timeout >= stream timeout
3. **Monitored on the client side**: MCP clients and n8n nodes have their own timeout handling

### Recommended Timeout Settings

| Component | Default | Recommended | Notes |
|-----------|---------|-------------|-------|
| Stream timeout (SDK) | 300s (5 min) | 300-600s | Configurable per stream |
| Proxy read_timeout | 60s | 600s+ | Must be >= stream timeout |
| Proxy connect_timeout | 60s | 60s | Typical value |
| Load balancer timeout | 60s | 600s+ | If behind load balancer |
| Client timeout (MCP) | 30s | 300s+ | Configurable per client |
| Client timeout (n8n) | Variable | Match stream timeout | Configure in node settings |

### Example: Long-Running Streams

For agents that process tasks longer than 5 minutes:

```python
from zyndai_agent import ZyndAIAgent, AgentConfig

config = AgentConfig(
name="Long Task Agent",
webhook_port=5000,
generative_ui=True,
)

agent = ZyndAIAgent(agent_config=config)

@agent.register_handler
async def handle_long_task(message, ui):
await ui.text("Starting long task...")

# Task takes 10 minutes
for i in range(600):
await asyncio.sleep(1)
if i % 60 == 0:
await ui.text(f"Progress: {i//60} minutes...")
```

And configure the stream timeout:

```python
# Client side: n8n node
# Set Stream Timeout to 600 seconds (10 minutes)

# Or: MCP client
import asyncio
from zyndai_mcp_server import tools

result = await tools.zyndai_subscribe_agent_stream(
agent_id="...",
timeout_seconds=600 # 10 minutes
)
```

## Rate Limiting

AG-UI streams are rate-limited to prevent abuse:

- **Default limit**: 10 concurrent streams per IP address per minute
- **Enforcement**: Applied at the agent webhook level (not the proxy)

If you need to adjust these limits, modify the `StreamRateLimiter` initialization in `webhook_communication.py`:

```python
self._stream_rate_limiter = StreamRateLimiter(
max_streams_per_ip=10, # Adjust as needed
window_seconds=60 # Time window in seconds
)
```

## Health Checks and Monitoring

### Health Check Endpoint

```bash
curl http://agent.example.com/health
# Returns: { "status": "healthy", "agent_id": "...", "uptime_seconds": 123 }
```

### Metrics Endpoint

Stream metrics are tracked in-memory and can be accessed via:

```python
from zyndai_agent.ui.metrics import get_metrics

metrics = get_metrics()
print(metrics.get_summary())
# Output:
# {
# "agui_events_emitted_total": 1523,
# "agui_active_streams": 2,
# "agui_stream_duration_avg_seconds": 45.3,
# "agui_stream_count_total": 87
# }
```

## DID Signature Verification

When deploying with signature verification enabled, ensure:

1. **Agent has a valid DID**: Generated during registration
2. **Clients have the agent's public key**: For verifying stream signatures
3. **Nginx/proxy passes through query parameters**: For DID and signature in `/ui/stream/<conversation_id>?sender_did=...&signature=...`

Example client request with signature:

```bash
curl "http://agent.example.com/ui/stream/conv-123?sender_did=did:key:z6MkhaXgBZDvotpK&signature=base64_signature"
```

## Production Deployment Checklist

- [ ] Proxy configured with `proxy_buffering off` and `proxy_read_timeout >= stream timeout`
- [ ] Stream timeout set to match expected task duration
- [ ] Rate limiting limits reviewed and adjusted if needed
- [ ] Health checks configured on load balancer
- [ ] Metrics monitoring in place (Prometheus, DataDog, etc.)
- [ ] Graceful shutdown configured (SIGTERM → emit RUN_ERROR)
- [ ] DID verification enabled for security
- [ ] SSL/TLS certificate configured for HTTPS
- [ ] Ngrok tunnel or public URL configured and verified
- [ ] Error logs monitored for connection issues

## Troubleshooting

### "Stream timeout after 5 minutes"

**Cause**: Proxy read_timeout is less than stream timeout

**Solution**: Increase proxy `read_timeout` to >= stream timeout

```nginx
proxy_read_timeout 600s; # 10 minutes
```

### "Rate limit exceeded. Max 10 concurrent streams per IP per minute"

**Cause**: Client exceeded rate limit

**Solution**:
1. Wait before opening more streams
2. Increase rate limit if legitimate use:

```python
self._stream_rate_limiter = StreamRateLimiter(
max_streams_per_ip=50, # Increased from 10
window_seconds=60
)
```

### "Invalid signature" when subscribing to stream

**Cause**: Sender DID or signature is invalid or missing

**Solution**:
1. Include `sender_did` and `signature` query parameters
2. Ensure client has agent's public key for verification
3. Check signature generation code in client

### Stream closes unexpectedly

**Cause**: Agent is shutting down or error occurred

**Check**: Look for RUN_ERROR event in stream output. See server logs for details.
Loading