https://github.com/alexsjones/sympozium
Run a fleet of AI agents on Kubernetes. Administer your cluster agentically
https://github.com/alexsjones/sympozium
agentic agentic-ai kubeclaw openclaw
Last synced: 4 months ago
JSON representation
Run a fleet of AI agents on Kubernetes. Administer your cluster agentically
- Host: GitHub
- URL: https://github.com/alexsjones/sympozium
- Owner: AlexsJones
- License: mit
- Created: 2026-02-23T09:53:24.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-02-27T20:13:34.000Z (4 months ago)
- Last Synced: 2026-02-28T14:58:32.411Z (4 months ago)
- Topics: agentic, agentic-ai, kubeclaw, openclaw
- Language: Go
- Homepage: https://sympozium.ai/
- Size: 9.95 MB
- Stars: 87
- Watchers: 1
- Forks: 17
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Roadmap: docs/roadmap.md
- Agents: AGENTS.md
Awesome Lists containing this project
README
Every agent is an ephemeral Pod.
Every policy is a CRD. Every execution is a Job.
Orchestrate multi-agent workflows and let agents diagnose, scale, and remediate your infrastructure.
Multi-tenant. Horizontally scalable. Safe by design.
From the creator of k8sgpt and llmfit
This project is under active development. API's will change, things will be break. Be brave.
---
### Quick Install (macOS / Linux)
**Homebrew:**
```bash
brew tap AlexsJones/sympozium
brew install sympozium
```
**Shell installer:**
```bash
curl -fsSL https://deploy.sympozium.ai/install.sh | sh
```
Then deploy to your cluster and activate your first agents:
```bash
sympozium install # deploys CRDs, controllers, and built-in PersonaPacks
sympozium # launch the TUI โ go to Personas tab, press Enter to onboard
```
Sympozium ships with **PersonaPacks** โ pre-configured bundles of agents that you activate with a few keypresses. No YAML required. See [PersonaPacks](#personapacks) below.
๐ **New here?** See the [Getting Started guide](docs/getting-started.md) โ install, deploy, onboard your first agent, and learn the TUI and CLI commands.
### Advanced: Helm Chart
For production and GitOps workflows, you can deploy the control plane separately using Helm and install the CLI independently.
#### Control Plane
**Prerequisites:** [cert-manager](https://cert-manager.io/) (for webhook TLS):
```bash
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.1/cert-manager.yaml
```
Deploy the Sympozium control plane:
```bash
helm install sympozium ./charts/sympozium
```
See [`charts/sympozium/values.yaml`](charts/sympozium/values.yaml) for configuration options (replicas, resources, external NATS, network policies, etc.).
#### CLI
Install the CLI on your local machine to connect to the cluster:
```bash
brew tap AlexsJones/sympozium && brew install sympozium
# or
curl -fsSL https://deploy.sympozium.ai/install.sh | sh
```
## Why Sympozium?
Sympozium serves **two powerful use cases** on one Kubernetes-native platform:
1. **Orchestrate fleets of AI agents** โ customer support, code review, data pipelines, or any domain-specific workflow. Each agent gets its own pod, RBAC, and network policy with proper tenant isolation.
2. **Administer the cluster itself agentically** โ point agents inward to diagnose failures, scale deployments, triage alerts, and remediate issues, all with Kubernetes-native isolation, RBAC, and audit trails.
Agentic frameworks like OpenClaw pioneered rich agent orchestration โ sub-agent registries, tool pipelines, channel integrations, and sandbox execution. But they run as **in-process monoliths** with file-based state, single-instance locks, and tightly coupled plugin systems.
Sympozium takes the same agentic control model and rebuilds it on Kubernetes primitives:
### Isolated Skill Sidecars โ a game-changer
Most agent frameworks dump every tool into one shared process. One bad `kubectl delete` and your whole agent environment is toast. Sympozium does this completely differently:
**Every skill runs in its own sidecar container** โ a separate, isolated process injected into the agent pod at runtime. Use skills to give agents cluster-admin capabilities (`kubectl`, `helm`, scaling) or domain-specific tools โ each with ephemeral least-privilege RBAC that's garbage-collected when the run finishes. Toggle a skill on, and the controller automatically:
- Injects a dedicated sidecar container with only the binaries that skill needs (`kubectl`, `helm`, `terraform`, etc.)
- Provisions **ephemeral, least-privilege RBAC** scoped to that single agent run โ no standing permissions, no god-roles
- Shares a `/workspace` volume so the agent can coordinate with the sidecar
- **Garbage-collects everything** when the run finishes โ containers, roles, bindings, all gone
This means you can give an agent full `kubectl` access for a troubleshooting run without worrying about leftover permissions. Skills are declared as CRDs, toggled per-instance in the TUI with a single keypress, and their containers are built and shipped alongside the rest of Sympozium. No plugins to install, no runtime to configure โ just Kubernetes-native isolation that scales.
> _"Give the agent tools, not trust."_ โ Whether it's orchestrating a fleet or administering the cluster, skills get exactly the permissions they declare, for exactly as long as the run lasts, and not a second longer.
### How it compares
| Concern | OpenClaw (in-process) | Sympozium (Kubernetes-native) |
|---------|----------------------|----------------------------|
| **Agent execution** | Shared memory, single process | Ephemeral **Pod** per invocation (K8s Job) |
| **Orchestration** | In-process registry + lane queue | **CRD-based** registry with controller reconciliation |
| **Sandbox isolation** | Long-lived Docker sidecar | Pod **SecurityContext** + PodSecurity admission |
| **IPC** | In-process EventEmitter | Filesystem sidecar + **NATS JetStream** |
| **Tool/feature gating** | 7-layer in-process pipeline | **Admission webhooks** + `SympoziumPolicy` CRD |
| **Persistent memory** | Files on disk (`~/.openclaw/`) | **ConfigMap** per instance, controller-managed |
| **Scheduled tasks** | Cron jobs / external scripts | **SympoziumSchedule CRD** with cron controller |
| **State** | SQLite + flat files | **etcd** (CRDs) + PostgreSQL + object storage |
| **Multi-tenancy** | Single-instance file lock | **Namespaced CRDs**, RBAC, NetworkPolicy |
| **Scaling** | Vertical only | **Horizontal** โ stateless control plane, HPA |
| **Channel connections** | In-process per channel | Dedicated **Deployment** per channel type |
| **Observability** | Application logs | `kubectl logs`, events, conditions, **k9s-style TUI** |
The result: every concept that OpenClaw manages in application code, Sympozium expresses as a Kubernetes resource โ then adds the ability to point agents at the cluster itself. Declarative, reconcilable, observable, and scalable.
---
### Deploy to Your Cluster
```bash
sympozium install # CRDs, controllers, webhook, NATS, RBAC, network policies
sympozium onboard # interactive setup wizard โ instance, provider, channel
sympozium # launch the interactive TUI (default command)
sympozium uninstall # clean removal
```
## Architecture
```mermaid
graph TB
subgraph K8S["Kubernetes Cluster"]
direction TB
subgraph CP["Control Plane"]
CM["Controller Manager
SympoziumInstance ยท AgentRun ยท PersonaPack
SympoziumPolicy ยท SkillPack ยท SympoziumSchedule"]
API["API Server
HTTP + WebSocket"]
WH["Admission Webhook
Policy enforcement"]
NATS[("NATS JetStream
Event bus")]
CM --- NATS
API --- NATS
WH -.- CM
end
subgraph SCHED["Scheduled Tasks"]
CS["SympoziumSchedule Controller
Cron-based reconciler"]
SROUTER["Schedule Router
NATS โ SympoziumSchedule CRD"]
CS -- "creates AgentRuns
on schedule" --> CM
SROUTER -- "creates / updates
SympoziumSchedule CRDs" --> CS
end
subgraph CH["Channel Pods ยท one Deployment per type"]
TG["Telegram"]
SL["Slack"]
DC["Discord"]
WA["WhatsApp"]
end
subgraph AP["Agent Pod ยท ephemeral K8s Job"]
direction LR
A1["Agent Container
LLM provider agnostic"]
IPC["IPC Bridge
fsnotify โ NATS"]
SB["Sandbox
optional sidecar"]
SKS["Skill Sidecars
kubectl, helm, etc.
auto-RBAC"]
A1 -. "/ipc volume" .- IPC
A1 -. optional .- SB
A1 -. "/workspace" .- SKS
end
subgraph SEC["Skill RBAC ยท ephemeral, least-privilege"]
SR["Role + RoleBinding
namespace-scoped
ownerRef โ AgentRun"]
SCR["ClusterRole + Binding
cluster-scoped
label-based cleanup"]
end
SKS -- "uses" --> SR
SKS -- "uses" --> SCR
CM -- "creates / deletes" --> SEC
subgraph MEM["Persistent Memory"]
MCM[("ConfigMap
<instance>-memory")]
A1 -- "reads /memory
MEMORY.md" --> MCM
CM -- "extracts & patches
memory markers" --> MCM
end
subgraph DATA["Data Layer"]
ETCD[("etcd
CRDs, state")]
PG[("PostgreSQL
sessions, history")]
SK[("SkillPack ConfigMaps
mounted at /skills")]
end
TG & SL & DC & WA -- "messages" --> NATS
NATS -- "tasks" --> IPC
IPC -- "channel msgs
schedule requests" --> NATS
NATS -- "schedule.upsert" --> SROUTER
end
USER(["User / Chat Client"]) -- "Telegram ยท Slack
Discord ยท WhatsApp" --> CH
ADMIN(["Operator / SRE"]) -- "sympozium TUI
kubectl ยท k9s" --> CP
style K8S fill:#0d1117,stroke:#30363d,color:#c9d1d9
style CP fill:#1a1a2e,stroke:#e94560,color:#fff
style SCHED fill:#1a1a2e,stroke:#f5a623,color:#fff
style CH fill:#16213e,stroke:#0f3460,color:#fff
style AP fill:#0f3460,stroke:#53354a,color:#fff
style MEM fill:#1c2333,stroke:#7c3aed,color:#fff
style SEC fill:#1c2333,stroke:#238636,color:#fff
style DATA fill:#161b22,stroke:#30363d,color:#c9d1d9
style NATS fill:#e94560,stroke:#fff,color:#fff
style USER fill:#238636,stroke:#fff,color:#fff
style ADMIN fill:#1f6feb,stroke:#fff,color:#fff
```
### How It Works
1. **A message arrives** via a channel pod (Telegram, Slack, etc.) and is published to the NATS event bus.
2. **The controller creates an AgentRun CR**, which reconciles into an ephemeral K8s Job โ an agent container + IPC bridge sidecar + optional sandbox + skill sidecars (with auto-provisioned RBAC).
3. **The agent container** calls the configured LLM provider (OpenAI, Anthropic, Azure, Ollama, or any OpenAI-compatible endpoint), with skills mounted as files, persistent memory injected from a ConfigMap, and tool sidecars providing runtime capabilities like `kubectl`.
4. **Results flow back** through the IPC bridge โ NATS โ channel pod โ user. The controller extracts structured results and memory updates from pod logs.
5. **Everything is a Kubernetes resource** โ instances, runs, policies, skills, and schedules are all CRDs. Lifecycle is managed by controllers. Access is gated by admission webhooks. Network isolation is enforced by NetworkPolicy. The TUI gives you k9s-style visibility into the entire system.
---
### Built-in Agent Tools
Every agent pod has these tools available out of the box (no skill sidecar required for native tools):
| Tool | Type | Description |
|------|------|-------------|
| `execute_command` | IPC (sidecar) | Execute shell commands (`kubectl`, `bash`, `curl`, `jq`, etc.) in the skill sidecar container. Timeout-configurable, working directory support. |
| `read_file` | Native | Read file contents from the pod filesystem (`/workspace`, `/skills`, `/tmp`, `/ipc`). Truncated at 100 KB. |
| `write_file` | Native | Create or overwrite files under `/workspace` or `/tmp`. Auto-creates parent directories. |
| `list_directory` | Native | List directory contents with type, size, and name. |
| `fetch_url` | Native | Fetch web pages or API endpoints. HTML is converted to readable plain text; JSON returned as-is. Supports custom headers, configurable max chars (default 50k). |
| `send_channel_message` | IPC (bridge) | Send a message through a connected channel (WhatsApp, Telegram, Discord, Slack). Routes via IPC bridge โ NATS โ channel pod. |
> **Native** tools run directly in the agent container. **IPC** tools communicate with sidecars or the IPC bridge via the shared `/ipc` volume. See the **[Tool Authoring Guide](docs/writing-tools.md)** for how to add your own.
### Built-in Skills (SkillPacks)
Skills are mounted as files into agent pods and optionally inject sidecar containers with runtime tools. Toggle skills per-instance in the TUI with `s` โ `Space`.
| SkillPack | Category | Sidecar | Description | Status |
|-----------|----------|---------|-------------|--------|
| `k8s-ops` | Kubernetes | โ
`kubectl`, `curl`, `jq` | Cluster inspection, workload management, troubleshooting, scaling. Full admin RBAC auto-provisioned per run. | **Stable** |
| `incident-response` | SRE | โ
| Structured incident triage โ gather context, diagnose root cause, suggest remediation. | **Alpha** |
| `code-review` | Development | โ | Code review guidelines and best practices for pull request analysis. | **Alpha** |
### Channels
Channels connect Sympozium to external messaging platforms. Each channel runs as a dedicated Kubernetes Deployment. Messages flow through NATS JetStream and are routed to AgentRuns by the channel router.
| Channel | Protocol | Self-chat | Status |
|---------|----------|-----------|--------|
| **WhatsApp** | WhatsApp Web (multidevice) via `whatsmeow` | โ
Owner can message themselves to interact with agents | **Stable** |
| **Telegram** | Bot API (`tgbotapi`) | โ
Owner can message themselves to interact with agents | **Stable** |
| **Discord** | Gateway WebSocket (`discordgo`) | โ | **Alpha** |
| **Slack** | Socket Mode (`slack-go`) | โ | **Alpha** |
> **Stable** โ tested and actively used. **Alpha** โ implemented but not yet production-tested.
---
## Custom Resources
Sympozium models every agentic concept as a Kubernetes Custom Resource:
| CRD | Kubernetes Analogy | Purpose |
|-----|--------------------|---------|
| `SympoziumInstance` | Namespace / Tenant | Per-user gateway โ channels, provider config, memory settings, skill bindings |
| `AgentRun` | Job | Single agent execution โ task, model, result capture, memory extraction |
| `SympoziumPolicy` | NetworkPolicy | Feature and tool gating โ what an agent can and cannot do |
| `SkillPack` | ConfigMap | Portable skill bundles โ kubectl, Helm, or custom tools โ mounted into agent pods as files, with optional sidecar containers for cluster ops |
| `SympoziumSchedule` | CronJob | Recurring tasks โ heartbeats, sweeps, scheduled runs with cron expressions |
| `PersonaPack` | Helm Chart / Operator Bundle | Pre-configured agent bundles โ activating a pack stamps out instances, schedules, and memory for each persona |
### PersonaPacks
PersonaPacks are the **recommended way to get started** with Sympozium. A PersonaPack is a CRD that bundles multiple pre-configured agent personas โ each with a system prompt, skills, tool policy, schedule, and memory seeds. Activating a pack is a single action: the PersonaPack controller stamps out all the Kubernetes resources automatically.
**Why PersonaPacks?**
Without PersonaPacks, setting up even one agent requires creating a Secret, SympoziumInstance, SympoziumSchedule, and memory ConfigMap by hand. PersonaPacks collapse that into: pick a pack โ enter your API key โ done.
**How it works:**
```
PersonaPack "platform-team" (3 personas)
โ
โโโ Activate via TUI (Enter on pack โ wizard โ API key โ confirm)
โ
โโโ Controller stamps out:
โโโ Secret: platform-team-openai-key
โโโ SympoziumInstance: platform-team-security-guardian
โ โโโ SympoziumSchedule: ...security-guardian-schedule (every 30m)
โ โโโ ConfigMap: ...security-guardian-memory (seeded)
โโโ SympoziumInstance: platform-team-sre-watchdog
โ โโโ SympoziumSchedule: ...sre-watchdog-schedule (every 5m)
โ โโโ ConfigMap: ...sre-watchdog-memory (seeded)
โโโ SympoziumInstance: platform-team-platform-engineer
โโโ SympoziumSchedule: ...platform-engineer-schedule (weekdays 9am)
โโโ ConfigMap: ...platform-engineer-memory (seeded)
```
All generated resources have `ownerReferences` pointing back to the PersonaPack โ delete the pack and everything gets garbage-collected.
**Built-in packs:**
| Pack | Category | Agents | Description |
|------|----------|--------|-------------|
| `platform-team` | Platform | Security Guardian, SRE Watchdog, Platform Engineer | Core platform engineering โ security audits, cluster health, manifest review |
| `devops-essentials` | DevOps | Incident Responder, Cost Analyzer | DevOps workflows โ incident triage, resource right-sizing |
**Activating a pack in the TUI:**
1. Launch `sympozium` โ the TUI opens on the **Personas** tab (view 1)
2. Select a pack and press **Enter** to start the onboarding wizard
3. Choose your AI provider and paste an API key
4. Optionally bind channels (Telegram, Slack, Discord, WhatsApp)
5. Confirm โ the controller creates all instances within seconds
**Activating via kubectl:**
```yaml
# 1. Create the provider secret
kubectl create secret generic my-pack-openai-key \
--from-literal=OPENAI_API_KEY=sk-...
# 2. Patch the PersonaPack with authRefs to trigger activation
kubectl patch personapack platform-team --type=merge -p '{
"spec": {
"authRefs": [{"provider": "openai", "secret": "my-pack-openai-key"}]
}
}'
```
The controller detects the `authRefs` change and reconciles โ creating SympoziumInstances, Schedules, and memory ConfigMaps for each persona.
**Writing your own PersonaPack:**
```yaml
apiVersion: sympozium.ai/v1alpha1
kind: PersonaPack
metadata:
name: my-team
spec:
description: "My custom agent team"
category: custom
version: "1.0.0"
personas:
- name: my-agent
displayName: "My Agent"
systemPrompt: |
You are a helpful assistant that monitors the cluster.
skills:
- k8s-ops
toolPolicy:
allow: [read_file, list_directory, execute_command, fetch_url]
schedule:
type: heartbeat
interval: "1h"
task: "Check cluster health and report any issues."
memory:
enabled: true
seeds:
- "Track recurring issues for trend analysis"
```
Apply it with `kubectl apply -f my-team.yaml`, then activate through the TUI.
### Skill Sidecars
SkillPacks can declare a **sidecar container** that is dynamically injected into the agent pod when the skill is active. The controller automatically creates scoped RBAC:
```
SympoziumInstance has skills: [k8s-ops]
โ AgentRun created
โ Controller resolves SkillPack "k8s-ops"
โ Finds sidecar: { image: skill-k8s-ops, rbac: [...] }
โ Injects sidecar container into pod
โ Creates Role + RoleBinding (namespace-scoped)
โ Creates ClusterRole + ClusterRoleBinding (cluster-wide access)
โ Pod runs with kubectl + RBAC available
โ On completion/deletion: all skill RBAC cleaned up
```
The `k8s-ops` built-in skill is the first proof of concept โ it provides a sidecar with `kubectl`, `curl`, and `jq` with full admin access to workload resources (pods, deployments, services, etc.) and cluster-wide read access to nodes, namespaces, and more. See the **[Skill Authoring Guide](docs/writing-skills.md)** for a full walkthrough of building your own skills. To enable a skill, toggle it on your instance:
```
# In the TUI: press 's' on an instance โ Space to toggle k8s-ops
# Or via kubectl:
kubectl patch sympoziuminstance --type=merge -p '{"spec":{"skills":[{"skillPackRef":"k8s-ops"}]}}'
```
### Security
Sympozium enforces defence-in-depth at every layer โ from network isolation to per-run RBAC:
| Layer | Mechanism | Scope |
|-------|-----------|-------|
| **Network** | `NetworkPolicy` deny-all egress on agent pods | Only the IPC bridge can reach NATS; agents cannot reach the internet or other pods |
| **Pod sandbox** | `SecurityContext` โ `runAsNonRoot`, UID 1000, read-only root filesystem | Every agent and sidecar container runs with least privilege |
| **Admission control** | `SympoziumPolicy` admission webhook | Feature and tool gates enforced before the pod is created |
| **Skill RBAC** | Ephemeral `Role`/`ClusterRole` per AgentRun | Each skill declares exactly the API permissions it needs โ the controller auto-provisions them at run start and revokes them on completion |
| **RBAC lifecycle** | `ownerReference` (namespace) + label-based cleanup (cluster) | Namespace RBAC is garbage-collected by Kubernetes. Cluster RBAC is cleaned up by the controller on AgentRun completion and deletion. |
| **Controller privilege** | `cluster-admin` binding | The controller needs `cluster-admin` to create arbitrary RBAC rules declared by SkillPacks (Kubernetes prevents RBAC escalation otherwise) |
| **Multi-tenancy** | Namespaced CRDs + Kubernetes RBAC | Instances, runs, and policies are namespace-scoped; standard K8s RBAC controls who can create them |
The skill sidecar RBAC model deserves special attention: permissions are **created on-demand** when an AgentRun starts, scoped to exactly the APIs the skill needs, and **deleted when the run finishes**. There is no standing god-role โ each run gets its own short-lived credentials. This is the Kubernetes-native equivalent of temporary IAM session credentials.
### Persistent Memory
Each `SympoziumInstance` can enable **persistent memory** โ a ConfigMap (`-memory`) containing `MEMORY.md` that is:
- Mounted read-only into every agent pod at `/memory/MEMORY.md`
- Prepended as context so the agent knows what it has learned
- Updated after each run โ the controller extracts memory markers from pod logs and patches the ConfigMap
This gives agents **continuity across runs** without external databases or file systems. Memory lives in etcd alongside all other cluster state.
### Scheduled Tasks (Heartbeats)
`SympoziumSchedule` resources define cron-based recurring agent runs โ perfect for automated cluster health checks, overnight alert reviews, resource right-sizing sweeps, or any domain-specific task:
```yaml
apiVersion: sympozium.ai/v1alpha1
kind: SympoziumSchedule
metadata:
name: daily-standup
spec:
instanceRef: alice
schedule: "0 9 * * *" # every day at 9am
type: heartbeat
task: "Review overnight alerts and summarize status"
includeMemory: true # inject persistent memory
concurrencyPolicy: Forbid # skip if previous run still active
```
Concurrency policies (`Forbid`, `Allow`, `Replace`) work like `CronJob.spec.concurrencyPolicy` โ a natural extension of Kubernetes semantics.
## Interactive TUI
Running `sympozium` with no arguments launches a **k9s-style interactive terminal UI** for full cluster-wide agentic management.
### Views
| Key | View | Description |
|-----|------|-------------|
| `1` | Personas | PersonaPack list โ press Enter to activate a pack and create agents |
| `2` | Instances | SympoziumInstance list with status, channels, memory config |
| `3` | Runs | AgentRun list with phase, duration, result preview |
| `4` | Policies | SympoziumPolicy list with feature gates |
| `5` | Skills | SkillPack list with file counts |
| `6` | Channels | Channel pod status (Telegram, Slack, Discord, WhatsApp) |
| `7` | Schedules | SympoziumSchedule list with cron, type, phase, run count |
| `8` | Pods | All sympozium pods with status and restarts |
### Keybindings
| Key | Action |
|-----|--------|
| `l` | View logs for the selected resource |
| `d` | Describe the selected resource (kubectl describe) |
| `x` | Delete the selected resource (with confirmation) |
| `Enter` | View details / select row |
| `Tab` | Cycle between views |
| `Esc` | Go back / close panel |
| `?` | Toggle help |
### Slash Commands
| Command | Description |
|---------|-------------|
| `/run ` | Create and submit an AgentRun |
| `/schedule ` | Create a SympoziumSchedule |
| `/memory ` | View persistent memory for an instance |
| `/personas` | Switch to PersonaPacks view |
| `/instances` `/runs` `/channels` `/schedules` | Switch views |
| `/delete ` | Delete a resource with confirmation |
## Getting Started
### 1. Install the CLI
```bash
curl -fsSL https://deploy.sympozium.ai/install.sh | sh
```
Detects your OS and architecture, downloads the latest release binary, and installs to `/usr/local/bin` (or `~/.local/bin`).
### 2. Deploy to your cluster
```bash
sympozium install
```
Applies CRDs, RBAC, controller manager, API server, admission webhook, NATS event bus, cert-manager (if not present), and network policies to your current kubectl context.
```bash
sympozium install --version v0.0.13 # specific version
```
### 3. Activate a PersonaPack (recommended)
Launch the TUI and activate one of the built-in PersonaPacks:
```bash
sympozium
```
The TUI opens on the **Personas** tab. Press **Enter** on a pack (e.g. `platform-team`) to start the onboarding wizard:
1. Choose your AI provider (OpenAI, Anthropic, Azure, Ollama, or custom)
2. Paste your API key
3. Pick a model
4. Optionally bind messaging channels
5. Confirm โ the controller creates all agent instances automatically
Within seconds you'll have multiple purpose-built agents running on schedules, each with their own skills, memory, and tool policies.
### Alternative: Manual onboard (single instance)
If you prefer to create a single instance manually:
```bash
sympozium onboard
```
The wizard walks you through five steps:
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Sympozium ยท Onboarding Wizard โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Step 1/5 โ Cluster check
Step 2/5 โ Name your SympoziumInstance
Step 3/5 โ Choose your AI provider
Step 4/5 โ Connect a channel (optional)
Step 5/5 โ Apply default policy
```
**Step 3** supports any GenAI provider:
| Provider | Base URL | API Key |
|----------|----------|---------|
| OpenAI | (default) | `OPENAI_API_KEY` |
| Anthropic | (default) | `ANTHROPIC_API_KEY` |
| Azure OpenAI | your endpoint | `AZURE_OPENAI_API_KEY` |
| Ollama | `http://ollama:11434/v1` | none |
| Any OpenAI-compatible | custom URL | custom |
### 4. Launch Sympozium
```bash
sympozium
```
The interactive TUI gives you full visibility โ browse instances, runs, schedules, and channels; view logs and describe output inline; submit agent runs with `/run `; check memory with `/memory `.
```bash
sympozium instances list # list instances
sympozium runs list # list agent runs
sympozium features enable browser-automation \
--policy default-policy # enable a feature gate
```
### 5. Remove Sympozium
```bash
sympozium uninstall
```
## Project Structure
```
sympozium/
โโโ api/v1alpha1/ # CRD type definitions (SympoziumInstance, AgentRun, SympoziumPolicy, SkillPack, SympoziumSchedule, PersonaPack)
โโโ cmd/ # Binary entry points
โ โโโ agent-runner/ # LLM agent runner (runs inside agent pods)
โ โโโ controller/ # Controller manager (reconciles all CRDs)
โ โโโ apiserver/ # HTTP + WebSocket API server
โ โโโ ipc-bridge/ # IPC bridge sidecar (fsnotify โ NATS)
โ โโโ webhook/ # Admission webhook (policy enforcement)
โ โโโ sympozium/ # CLI + interactive TUI
โโโ internal/ # Internal packages
โ โโโ controller/ # Kubernetes controllers (6 reconcilers incl. PersonaPack)
โ โโโ orchestrator/ # Agent pod builder & spawner
โ โโโ apiserver/ # API server handlers
โ โโโ eventbus/ # NATS JetStream event bus
โ โโโ ipc/ # IPC bridge (fsnotify + NATS)
โ โโโ webhook/ # Policy enforcement webhooks
โ โโโ session/ # Session persistence (PostgreSQL)
โ โโโ channel/ # Channel base types
โโโ channels/ # Channel pod implementations (Telegram, Slack, Discord, WhatsApp)
โโโ images/ # Dockerfiles for all components
โโโ config/ # Kubernetes manifests
โ โโโ crd/bases/ # CRD YAML definitions
โ โโโ manager/ # Controller deployment
โ โโโ rbac/ # ClusterRole, bindings
โ โโโ webhook/ # Webhook configuration
โ โโโ network/ # NetworkPolicy for agent isolation
โ โโโ nats/ # NATS JetStream deployment
โ โโโ cert/ # TLS certificate resources
โ โโโ personas/ # Built-in PersonaPack definitions
โ โโโ skills/ # Built-in SkillPack definitions
โ โโโ policies/ # Default SympoziumPolicy presets
โ โโโ samples/ # Example CRs
โโโ migrations/ # PostgreSQL schema migrations
โโโ docs/ # Design documentation
โโโ Makefile
โโโ README.md
```
## Key Design Decisions
| Decision | Kubernetes Primitive | Rationale |
|----------|---------------------|-----------|
| **One Pod per agent run** | Job | Blast-radius isolation, resource limits, automatic cleanup โ each agent is as ephemeral as a CronJob pod |
| **Filesystem IPC** | emptyDir volume | Agent writes to `/ipc/`, bridge sidecar watches via fsnotify and publishes to NATS โ language-agnostic, zero dependencies in agent container |
| **NATS JetStream** | StatefulSet | Durable pub/sub with replay โ channels and control plane communicate without direct coupling |
| **NetworkPolicy isolation** | NetworkPolicy | Agent pods get deny-all egress; only the IPC bridge connects to the event bus โ agents cannot reach the internet or other pods |
| **Policy-as-CRD** | Admission Webhook | `SympoziumPolicy` resources gate tools, sandboxes, and features โ enforced at admission time, not at runtime |
| **Memory-as-ConfigMap** | ConfigMap | Persistent agent memory lives in etcd โ no external database, no file system, fully declarative and backed up with cluster state |
| **Schedule-as-CRD** | CronJob analogy | `SympoziumSchedule` resources define recurring tasks with cron expressions โ the controller creates AgentRuns, not the user |
| **Skills-as-ConfigMap** | ConfigMap volume | SkillPacks generate ConfigMaps mounted into agent pods โ portable, versionable, namespace-scoped |
| **Skill sidecars with auto-RBAC** | Role / ClusterRole | SkillPacks can declare sidecar containers with RBAC rules โ the controller injects the container and provisions ephemeral, least-privilege RBAC per run |
| **PersonaPacks** | Operator Bundle | Pre-configured agent bundles โ the controller stamps out SympoziumInstances, Schedules, and memory ConfigMaps. Activating a pack is a single TUI action |
## Configuration
| Variable | Component | Description |
|----------|-----------|-------------|
| `EVENT_BUS_URL` | All | NATS server URL |
| `DATABASE_URL` | API Server | PostgreSQL connection string |
| `INSTANCE_NAME` | Channels | Owning SympoziumInstance name |
| `MEMORY_ENABLED` | Agent Runner | Whether persistent memory is active |
| `TELEGRAM_BOT_TOKEN` | Telegram | Bot API token |
| `SLACK_BOT_TOKEN` | Slack | Bot OAuth token |
| `DISCORD_BOT_TOKEN` | Discord | Bot token |
| `WHATSAPP_ACCESS_TOKEN` | WhatsApp | Cloud API access token |
## Development
```bash
make test # run tests (46 passing)
make lint # run linter
make manifests # generate CRD manifests
make run # run controller locally (needs kubeconfig)
```
## License
Apache License 2.0