Appearance
System Architecture
This page is a single-page deep dive into how Agentcy is structured. If you want the high-level pitch, read Platform Overview first.
At a glance
Agentcy is a Rust workspace + a Next.js frontend + three data stores. Everything is self-hostable.
┌───────────────────────────┐
│ Browser / SDK / CLI │
└─────────────┬─────────────┘
│ HTTPS + SSE + WS
┌─────────────▼─────────────┐
│ frontend (Next.js 16) │
└─────────────┬─────────────┘
│ /api/v1/*
┌─────────────▼─────────────┐
│ agentcy-api (Axum 0.8) │
│ JWT → policy → handlers │
└──┬────────┬──────────┬────┘
│ │ │
┌─────────────────┘ │ └──────────────────┐
│ │ │
┌─────────▼─────────┐ ┌────────────▼──────────┐ ┌──────────────▼─────────────┐
│ PostgreSQL │ │ Neo4j │ │ Redis │
│ (org / auth / │ │ (knowledge graph, │ │ (queues, pub/sub, │
│ config / runs) │ │ realm-partitioned) │ │ rate limits) │
└───────────────────┘ └───────────────────────┘ └────────────────────────────┘Additional runtime dependencies, all optional:
- Worker daemon (
agentcy-worker-bin) — off-process job execution. - OpenFang sidecar — SubAgent orchestrator (disabled by default).
- WhatsApp gateway — a Node.js Baileys process, auto-spawned from the API.
- LLM provider — OpenAI, Anthropic, Google, Ollama, vLLM, LM Studio.
- Object storage — S3-compatible bucket for artifacts (or local FS in dev).
The Rust workspace
The backend lives in backend/ as a Cargo workspace with 29 crates. Crates group by responsibility; connectors live under backend/sources/agentcy-source-*.
| Layer | Crates |
|---|---|
| HTTP surface | agentcy-api, agentcy-ws |
| Auth | agentcy-auth |
| Policy | agentcy-policy |
| Data stores | agentcy-db, agentcy-graph, agentcy-storage |
| Retrieval | agentcy-rag, agentcy-memory, agentcy-code-intel |
| Ingestion | agentcy-ingest + 26 agentcy-source-* crates |
| Chat & agents | agentcy-chat, agentcy-agent, agentcy-agents, agentcy-agent-bin |
| Execution | agentcy-worker, agentcy-worker-bin, agentcy-sandbox, agentcy-ciab-client, agentcy-durable |
| Scheduling | agentcy-tasks |
| Channels | agentcy-whatsapp, agentcy-slack-bot, agentcy-slack-channel, agentcy-plugins |
| Voice | agentcy-voice |
| CLIs | agentcy-cli, agentcy-proxy-cli |
| Shared | agentcy-core, agentcy-sdk |
For a one-line purpose per crate, see the Crate Map reference.
Request lifecycle
A typical authenticated request from the browser:
┌─ POST /api/v1/chat/conversations/:id/messages
│
├─ 1. CORS + compression layers (tower-http)
│
├─ 2. auth_middleware (agentcy-auth)
│ ├─ Local provider → HS256 verify via JWT_SECRET
│ └─ OIDC provider → RS256 verify via JWKS (cached)
│ └── sets Extension<UserContext> { user_id, org_id, role }
│
├─ 3. policy_middleware (agentcy-policy, if enabled)
│ ├─ derive action from (method, path) → "chat.send"
│ └─ evaluate Rego rules vs. {subject, action, resource, env}
│ ↳ deny[msg] → 403
│
├─ 4. handler (routes/chat.rs::send_message)
│ ├─ load tool catalog (agentcy-chat::ToolCatalog)
│ ├─ stream LLM + tool calls (agentcy-agent providers)
│ ├─ gate risky tools (ApprovalRegistry, blocks on oneshot)
│ ├─ execute tool (connector .execute_tool)
│ ├─ record events (activity log, conversation history)
│ └─ SSE chunks → browser
│
└─ 5. response drains, middlewares completeKey properties:
- Middleware ordering matters. Auth runs before policy; policy receives a populated
UserContext. - Streaming is SSE, not WebSocket. WebSockets are used for presence / graph updates only, via
agentcy-ws. - Tool execution is in-process by default for connector tools. CIAB tools go through a sandbox (local process or EC2). Heavy jobs go through
agentcy-worker.
Data stores
PostgreSQL
The primary system of record. Every table carries org_id. Schema lives in backend/crates/agentcy-db/migrations/. See the Database Schema reference.
Notable tables:
users,orgs,org_membershipssources,source_jobs,sync_historyconversations,messages,tool_callstasks,task_runs,task_recommendationswebhooks,webhook_deliverieschannels,channel_bindingspolicies,policy_sources,policy_audit_logskills,approvalsmemory_entries,memory_runs
Neo4j
Holds the knowledge graph. Nodes and edges carry a realm property so queries can be scoped to a domain (e.g. infrastructure, crm, design). See Knowledge Graph & Realms.
Queries are authored in Cypher, executed via agentcy-graph. The API exposes both raw Cypher (behind policy) and higher-level semantic search via agentcy-rag.
Redis
Used for:
- Job queues —
agentcy-workerreads from streams - Pub/sub — realtime events (
ConnectorEventBus) - Caching — JWKS, throttles, short-lived approval tokens
The connector model
Connectors are dual-role. Each agentcy-source-* crate can implement two traits:
IngestionSource— batch ETL into the knowledge graph.ConnectorToolProvider— live tools exposed to chat (e.g.github.list_pulls,aws.s3_list_objects).
Tools are not dumped into the LLM prompt. Instead, four catalog meta-tools (list_connectors, search_connector_tools, execute_connector_tool, request_connector_access) let the model page through the catalog on demand. See Agent Loop for details.
Connectors register in agentcy-api::state::AppState::source_registry at boot. Validation (validate_config) runs at creation so bad credentials fail fast.
Frontend
frontend/ is a Next.js 16 App Router project using React 19, shadcn/ui (Ark UI primitives), TanStack Query, Tailwind v4. Top-level dashboard sections mirror backend routes:
/chat,/graph,/connectors,/ingest/tasks,/workers,/channels,/orchestrator/skills,/artifacts,/memory,/coding-agents/security(api keys + policies),/activity,/settings,/admin,/embed
All data fetching goes through frontend/lib/api/client.ts, which centralizes JWT injection and error handling. Mutations use useMutation + invalidateQueries.
Feature flags
Several subsystems are compile-time + runtime gated. See backend/crates/agentcy-api/src/config.rs (FeaturesConfig):
| Flag | Default | What it enables |
|---|---|---|
rag | on | /rag routes, vector search |
workers | on | /workers routes, worker auth |
orchestrator | off | /orchestrator + OpenFang |
voice | off | /voice routes, STT/TTS |
policies | off | /policies routes + policy middleware |
connectors-dev | on (dev) | GitHub, K8s, OpenAPI, Remote, MCP, CIAB, OS, Git, Jenkins, Figma, Remotion |
connectors-cloud | on (dev) | AWS, GCP, Vercel, Supabase, LocalStack, Firecrawl, WebSearch, ElevenLabs, Runway, Slack, Google Workspace, Read.ai, HubSpot, Grafana |
connectors-data | on (dev) | SQL, MongoDB, Power BI |
Health checks (/api/v1/health) report which features are enabled so clients can adapt.
How requests cross process boundaries
Not everything runs in the API process:
- Worker jobs — handler enqueues a Redis stream entry, returns a job id. The worker daemon dequeues, runs the source, writes results to Postgres and Neo4j, and fires events back over Redis pub/sub so the UI gets a live update.
- CIAB tools — handler calls
agentcy-ciab-clientover HTTP/IPC to the sandbox runtime (local process or EC2 instance), streams stdout back as SSE. - WhatsApp — handler calls the WhatsApp gateway (Node.js Baileys), which owns the long-lived websocket to Meta.
- OpenFang — handler proxies to the OpenFang sidecar when orchestration features are used.
If any of these sidecars is missing, the API returns a 503 with a clear error — not a crash.
Observability
- Tracing —
tracing+tracing-subscriberacross all crates. Configure withRUST_LOG. - Activity feed — every org-scoped action writes an entry the UI can render (
/activity). - Audit log — policy decisions persist to
policy_audit_logwhen policies are enabled. - Health —
/api/v1/healthreturns feature status and dependency reachability (Postgres, Neo4j, Redis, LLM provider).
Where to go next
- Platform Overview — the "why" version of this page.
- Agent Loop — how chat, tools, approvals fit together.
- Ingestion Pipelines — how data flows into the graph.
- Crate Map — one line per crate.
- REST API — the wire format.