This file helps AI coding agents (Copilot, Cursor, Cline, etc.) understand the Sympozium project structure and development workflow.
Sympozium is a Kubernetes-native agent orchestration platform written in Go. Every AI agent runs as an ephemeral Kubernetes pod (Job), with policy enforcement via CRDs, admission webhooks, and RBAC. Communication flows through NATS JetStream and a filesystem-based IPC bridge.
- Language: Go 1.25+
- Module:
github.com/sympozium-ai/sympozium - K8s API version:
sympozium.ai/v1alpha1
api/v1alpha1/ # CRD type definitions (Agent, AgentRun, SympoziumPolicy, SkillPack, SympoziumSchedule, Ensemble, Model, MCPServer, SympoziumConfig, ModelConnection)
cmd/
agent-runner/ # Agent container — LLM loop + tool execution
apiserver/ # HTTP + WebSocket API server
controller/ # Controller manager (all reconcilers + routers)
ipc-bridge/ # IPC bridge sidecar (fsnotify → NATS)
web-proxy/ # Web proxy (OpenAI-compat API + MCP gateway)
node-probe/ # Node probe DaemonSet (discovers inference providers on nodes)
sympozium/ # CLI + TUI (Bubble Tea)
webhook/ # Admission webhook server
channels/
telegram/ # Channel pod — Telegram bot
slack/ # Channel pod — Slack (Socket Mode + Events API)
discord/ # Channel pod — Discord bot
whatsapp/ # Channel pod — WhatsApp
config/
crd/bases/ # Generated CRD YAML manifests
manager/ # Controller manager deployment
personas/ # Built-in Ensemble YAML definitions
rbac/ # RBAC roles
samples/ # Sample CR YAML files
skills/ # Built-in SkillPack YAML definitions
policies/ # Built-in SympoziumPolicy presets
webhook/ # Webhook configuration
images/ # Dockerfiles for all components
internal/
apiserver/ # API server implementation
channel/ # Channel types
controller/ # Reconcilers (AgentRun, Agent, SympoziumPolicy, SympoziumSchedule, SkillPack, Ensemble) + routers (Channel, Schedule)
eventbus/ # NATS JetStream client + topic constants
ipc/ # IPC bridge (fsnotify watcher, protocol, file handlers)
orchestrator/ # Pod builder + spawner for agent Jobs
session/ # Session store
webhook/ # Policy enforcer
webproxy/ # Web proxy handlers (OpenAI, MCP, rate limiting)
migrations/ # PostgreSQL schema migrations
test/integration/ # Integration test scripts (shell)
docs/ # Design & contributor documentation
| CRD | Purpose |
|---|---|
Agent |
An agent identity — provider config, model, enabled skills, channel bindings |
AgentRun |
A single agent invocation — task, result, phase lifecycle |
SympoziumPolicy |
Policy rules enforced by the admission webhook |
SkillPack |
Bundled skills (Markdown instructions) + optional sidecar container + RBAC |
SympoziumSchedule |
Cron-based recurring AgentRun creation (heartbeat, scheduled, sweep) |
Ensemble |
Pre-configured agent bundles — stamps out Agents, Schedules, and memory automatically |
Model |
Cluster-local inference — GGUF/HuggingFace source, llama-cpp/vllm/tgi backend, OpenAI-compatible endpoint |
MCPServer |
Managed MCP server lifecycle — stdio or HTTP transport, tool discovery, allow/deny filtering |
SympoziumConfig |
Platform-wide singleton — gateway, canary, and pricing settings |
ModelConnection |
Reusable namespaced model route for persistent harnesses and native Celln runs |
Type definitions live in api/v1alpha1/. After modifying types, regenerate with:
make generate # deepcopy + CRD manifests
make manifests # CRD YAML only- Go 1.25+
- Docker
- Kind (Kubernetes in Docker)
- kubectl
- An LLM API key (e.g.
OPENAI_API_KEY)
# Create cluster
kind create cluster --name kind
# Install CRDs
make install
# Build all images
make docker-build TAG=v0.1.0
# Load images into Kind (all components)
for img in controller apiserver ipc-bridge webhook agent-runner web-proxy \
channel-telegram channel-slack channel-discord channel-whatsapp \
skill-k8s-ops skill-sre-observability skill-llmfit; do
kind load docker-image ghcr.io/sympozium-ai/sympozium/$img:v0.1.0 --name kind
done
# Deploy the control plane
kubectl apply -k config/After code changes:
# Build everything
make build
# Run unit tests
make test
# Build specific image + reload into Kind
make docker-build-agent-runner TAG=v0.1.0
kind load docker-image ghcr.io/sympozium-ai/sympozium/agent-runner:v0.1.0 --name kind
# Restart the controller to pick up new images
kubectl rollout restart deployment sympozium-controller-manager -n sympozium-systemmake build # Build all binaries
make test # Run unit tests with race detector
make test-short # Run short tests only
make test-integration # Run all integration tests (requires Kind + API key)
(cd web && npm run test:stubbed) # Console Cypress specs that stub every API call (no cluster; needs `npx vite` running; CI runs these on web/** PRs)
make vet # go vet
make fmt # gofmt
make tidy # go mod tidy
make docker-build # Build all Docker images
make docker-build-<name> TAG=v0.1.0 # Build a specific image
make generate # Regenerate deepcopy + CRD manifests
make manifests # Regenerate CRD YAML only
make clean # Remove build artifactsIntegration tests live in test/integration/ and run against a real Kind cluster with a real LLM.
# All integration tests
make test-integration
# Single test
./test/integration/test-write-file.sh
# Override model or timeout
TEST_MODEL=gpt-5.2 TEST_TIMEOUT=180 ./test/integration/test-write-file.sh| Test | What it validates |
|---|---|
test-write-file.sh |
write_file tool — agent writes a file, script verifies content |
test-anthropic-write-file.sh |
write_file tool using Anthropic provider — validates provider parity |
test-k8s-ops-nodes.sh |
k8s-ops skill — agent runs kubectl via sidecar |
test-llmfit-cluster-fit.sh |
llmfit skill — agent runs node-level llmfit placement probe workflow |
test-telegram-channel.sh |
Telegram channel deployment + message flow |
test-slack-channel.sh |
Slack channel deployment (Socket Mode) |
test-web-proxy-api.sh |
Web proxy API — healthz, auth, models, chat completions (blocking + streaming), MCP SSE |
See docs/writing-integration-tests.md for the full guide and template. Tests follow this pattern:
- Create an
Agent+AgentRunwith a deterministic task - Poll
status.phaseuntilSucceededorFailed - Validate results (pod logs, status, filesystem)
- Clean up all test resources
Add new tests to the test-integration target in the Makefile.
The agent-runner has 8 built-in tools defined in cmd/agent-runner/tools.go:
| Tool | Category | Description |
|---|---|---|
execute_command |
IPC (sidecar) | Run shell commands in the skill sidecar |
read_file |
Native | Read file contents |
write_file |
Native | Write/create files |
edit_file |
Native | Apply one or more exact-string (unique-match) replacements to a file (atomic, all-or-nothing) |
list_directory |
Native | List directory contents |
send_channel_message |
IPC (bridge) | Send messages to Telegram/Slack/Discord/WhatsApp |
fetch_url |
Native | HTTP GET a URL and return the body |
schedule_task |
IPC (bridge) | Create/update/suspend/resume/delete SympoziumSchedule CRDs |
See docs/writing-tools.md for the full guide on adding new tools.
Agent tool writes JSON → /ipc/<dir>/*.json → fsnotify watcher → NATS publish → Controller handles
Directories: /ipc/tools/ (sidecar exec), /ipc/messages/ (channel messages), /ipc/schedules/ (schedule requests).
Key topics in internal/eventbus/types.go:
agent.run.requested/started/completed/failed— AgentRun lifecyclechannel.message.received/send— Channel message flowschedule.upsert— Agent self-scheduling requeststool.exec.request/result— Sidecar tool execution
Each Agent has a ConfigMap (<name>-memory) mounted at /memory/MEMORY.md. The controller extracts memory markers (__SYMPOZIUM_MEMORY__...__SYMPOZIUM_MEMORY_END__) from agent output and patches the ConfigMap.
SkillPacks are CRDs containing Markdown instructions + optional sidecar definitions. When enabled on an Agent, skills are mounted at /skills/ and sidecars are injected into agent pods. See docs/writing-skills.md.
| Document | Location | Content |
|---|---|---|
| Design document | docs/sympozium-design.md |
Full architecture, CRD schemas, data flow, security model |
| Writing tools | docs/writing-tools.md |
How to add new agent tools |
| Writing skills | docs/writing-skills.md |
How to create SkillPack CRDs |
| Writing integration tests | docs/writing-integration-tests.md |
Test patterns and templates |
| Web endpoint skill | docs/skill-web-endpoint.md |
How to expose agents as HTTP APIs (OpenAI-compat + MCP) |
| Serving mode | docs/serving-mode.md |
How serving mode works for long-lived agent deployments |
| Sample CRs | config/samples/ |
Example Agent, AgentRun, SympoziumPolicy, SympoziumSchedule, SkillPack |
| CRD definitions | api/v1alpha1/ |
Go type definitions for all CRDs |
| Built-in Ensembles | config/personas/ |
Pre-configured agent bundles (platform-team, devops-pipeline-example) |
- Add constant + definition + handler in
cmd/agent-runner/tools.go - If IPC-based, add watcher in
internal/ipc/bridge.goand topic ininternal/eventbus/types.go - If it needs a controller handler, add a router in
internal/controller/ - Rebuild
agent-runner(andipc-bridge/controllerif changed) - Write an integration test in
test/integration/ - Document in
docs/writing-tools.md
- Create
channels/<name>/main.go - Create
images/channel-<name>/Dockerfile - Add to
CHANNELSlist inMakefile - The controller's
buildChannelDeploymentininternal/controller/agent_controller.gohandles deployment
- Edit type in
api/v1alpha1/<name>_types.go - Run
make generateto regenerate deepcopy and CRD YAML - Run
make installto apply updated CRDs to cluster - Update the reconciler in
internal/controller/
- Create a YAML file in
config/personas/<name>.yaml - Define personas with system prompts, skills, schedules, and memory seeds
- Apply:
kubectl apply -f config/personas/<name>.yaml - Activate via the TUI Ensembles tab or by patching
spec.authRefswith kubectl
# Compile check
go build ./...
# Rebuild affected images
make docker-build-<component> TAG=v0.1.0
# Load into Kind
kind load docker-image ghcr.io/sympozium-ai/sympozium/<component>:v0.1.0 --name kind
# Restart controller if controller/ipc-bridge/agent-runner changed
kubectl rollout restart deployment sympozium-controller-manager -n sympozium-system