Skip to content

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-*.

LayerCrates
HTTP surfaceagentcy-api, agentcy-ws
Authagentcy-auth
Policyagentcy-policy
Data storesagentcy-db, agentcy-graph, agentcy-storage
Retrievalagentcy-rag, agentcy-memory, agentcy-code-intel
Ingestionagentcy-ingest + 26 agentcy-source-* crates
Chat & agentsagentcy-chat, agentcy-agent, agentcy-agents, agentcy-agent-bin
Executionagentcy-worker, agentcy-worker-bin, agentcy-sandbox, agentcy-ciab-client, agentcy-durable
Schedulingagentcy-tasks
Channelsagentcy-whatsapp, agentcy-slack-bot, agentcy-slack-channel, agentcy-plugins
Voiceagentcy-voice
CLIsagentcy-cli, agentcy-proxy-cli
Sharedagentcy-core, agentcy-sdk

For a one-line purpose per crate, see the Crate Map reference.

Request lifecycle

Request lifecycle: client → CORS → auth → policy → handler, with fan-out to Postgres, Neo4j, Redis, and LLM/tool providers; response streams back.

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 complete

Key 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_memberships
  • sources, source_jobs, sync_history
  • conversations, messages, tool_calls
  • tasks, task_runs, task_recommendations
  • webhooks, webhook_deliveries
  • channels, channel_bindings
  • policies, policy_sources, policy_audit_log
  • skills, approvals
  • memory_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 queuesagentcy-worker reads 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):

FlagDefaultWhat it enables
ragon/rag routes, vector search
workerson/workers routes, worker auth
orchestratoroff/orchestrator + OpenFang
voiceoff/voice routes, STT/TTS
policiesoff/policies routes + policy middleware
connectors-devon (dev)GitHub, K8s, OpenAPI, Remote, MCP, CIAB, OS, Git, Jenkins, Figma, Remotion
connectors-cloudon (dev)AWS, GCP, Vercel, Supabase, LocalStack, Firecrawl, WebSearch, ElevenLabs, Runway, Slack, Google Workspace, Read.ai, HubSpot, Grafana
connectors-dataon (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-client over 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

  • Tracingtracing + tracing-subscriber across all crates. Configure with RUST_LOG.
  • Activity feed — every org-scoped action writes an entry the UI can render (/activity).
  • Audit log — policy decisions persist to policy_audit_log when policies are enabled.
  • Health/api/v1/health returns feature status and dependency reachability (Postgres, Neo4j, Redis, LLM provider).

Where to go next

Built by AgentcyLabs. For in-house deployment or Agentcy Cloud (PaaS) access, visit agentcylabs.com.