Skip to content

Commit 432355b

Browse files
AlexsJonesclaude
andcommitted
feat!: rename PersonaPack to Ensemble + canvas-first builder
BREAKING CHANGE: The PersonaPack CRD has been renamed to Ensemble. All API endpoints, labels, controllers, and UI references updated. Rename (every layer): - CRD: PersonaPack → Ensemble, PersonaPackSpec → EnsembleSpec, etc. - API: /api/v1/personapacks → /api/v1/ensembles - Labels: sympozium.ai/persona-pack → sympozium.ai/ensemble - Controller: PersonaPackReconciler → EnsembleReconciler - Frontend: all types, hooks, pages, components, routes - TUI/CLI: all references in cmd/sympozium/main.go - Docs: personapacks.md → ensembles.md, writing guide, architecture - Helm: CRD YAML, RBAC, templates - Cypress: all test files renamed and updated - Integration tests: renamed and updated - "Persona" retained for individual agents within an ensemble Canvas-first ensemble builder: - Provider setup gate (select provider + auth before canvas) - ReactFlow canvas with add/remove persona nodes and drag-to-connect edges - PersonaConfigPanel side panel with provider-aware model selector (useModelList with direct browser fetch fallback for LAN providers) - EnsembleSettingsPanel for name, description, workflow type, shared memory - Shared memory defaults to ON for new ensembles with toolbar toggle - Ensemble name input directly in toolbar for discoverability - POST /api/v1/ensembles (create) and POST /api/v1/ensembles/{name}/clone - Route: /ensembles/new with "New Ensemble" button on list page City distance workflow E2E test: - Two-agent sequential ensemble (lead investigator + fact checker) - Validates shared memory write by lead, read by checker - Tests full lifecycle: create → activate → dispatch → verify → UI Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 008266e commit 432355b

108 files changed

Lines changed: 2819 additions & 1134 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENTS.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Sympozium is a **Kubernetes-native agent orchestration platform** written in Go.
1717
## Repository Layout
1818

1919
```
20-
api/v1alpha1/ # CRD type definitions (SympoziumInstance, AgentRun, SympoziumPolicy, SkillPack, SympoziumSchedule, PersonaPack)
20+
api/v1alpha1/ # CRD type definitions (SympoziumInstance, AgentRun, SympoziumPolicy, SkillPack, SympoziumSchedule, Ensemble)
2121
cmd/
2222
agent-runner/ # Agent container — LLM loop + tool execution
2323
apiserver/ # HTTP + WebSocket API server
@@ -35,7 +35,7 @@ channels/
3535
config/
3636
crd/bases/ # Generated CRD YAML manifests
3737
manager/ # Controller manager deployment
38-
personas/ # Built-in PersonaPack YAML definitions
38+
personas/ # Built-in Ensemble YAML definitions
3939
rbac/ # RBAC roles
4040
samples/ # Sample CR YAML files
4141
skills/ # Built-in SkillPack YAML definitions
@@ -45,7 +45,7 @@ images/ # Dockerfiles for all components
4545
internal/
4646
apiserver/ # API server implementation
4747
channel/ # Channel types
48-
controller/ # Reconcilers (AgentRun, SympoziumInstance, SympoziumPolicy, SympoziumSchedule, SkillPack, PersonaPack) + routers (Channel, Schedule)
48+
controller/ # Reconcilers (AgentRun, SympoziumInstance, SympoziumPolicy, SympoziumSchedule, SkillPack, Ensemble) + routers (Channel, Schedule)
4949
eventbus/ # NATS JetStream client + topic constants
5050
ipc/ # IPC bridge (fsnotify watcher, protocol, file handlers)
5151
orchestrator/ # Pod builder + spawner for agent Jobs
@@ -68,7 +68,7 @@ docs/ # Design & contributor documentation
6868
| `SympoziumPolicy` | Policy rules enforced by the admission webhook |
6969
| `SkillPack` | Bundled skills (Markdown instructions) + optional sidecar container + RBAC |
7070
| `SympoziumSchedule` | Cron-based recurring AgentRun creation (heartbeat, scheduled, sweep) |
71-
| `PersonaPack` | Pre-configured agent bundles — stamps out Instances, Schedules, and memory automatically |
71+
| `Ensemble` | Pre-configured agent bundles — stamps out Instances, Schedules, and memory automatically |
7272

7373
Type definitions live in `api/v1alpha1/`. After modifying types, regenerate with:
7474

@@ -251,7 +251,7 @@ SkillPacks are CRDs containing Markdown instructions + optional sidecar definiti
251251
| Serving mode | `docs/serving-mode.md` | How serving mode works for long-lived agent deployments |
252252
| Sample CRs | `config/samples/` | Example SympoziumInstance, AgentRun, SympoziumPolicy, SympoziumSchedule, SkillPack |
253253
| CRD definitions | `api/v1alpha1/` | Go type definitions for all CRDs |
254-
| Built-in PersonaPacks | `config/personas/` | Pre-configured agent bundles (platform-team, devops-essentials) |
254+
| Built-in Ensembles | `config/personas/` | Pre-configured agent bundles (platform-team, devops-essentials) |
255255

256256
---
257257

@@ -277,7 +277,7 @@ SkillPacks are CRDs containing Markdown instructions + optional sidecar definiti
277277
3. Run `make install` to apply updated CRDs to cluster
278278
4. Update the reconciler in `internal/controller/`
279279

280-
### Adding a PersonaPack
280+
### Adding a Ensemble
281281
1. Create a YAML file in `config/personas/<name>.yaml`
282282
2. Define personas with system prompts, skills, schedules, and memory seeds
283283
3. Apply: `kubectl apply -f config/personas/<name>.yaml`

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,12 @@ test-integration: ## Run integration tests (requires Kind cluster + API keys)
7171
./test/integration/test-mcp-bridge.sh
7272
./test/integration/test-lifecycle-hooks.sh
7373

74-
integration-tests: ## Run API smoke regression tests (PersonaPacks, ad-hoc Instances, Skills, Policies, Schedules)
74+
integration-tests: ## Run API smoke regression tests (Ensembles, ad-hoc Instances, Skills, Policies, Schedules)
7575
bash ./test/integration/test-api-smoke.sh
76-
bash ./test/integration/test-api-personapack-provider-switch.sh
77-
bash ./test/integration/test-api-personapack-adhoc-correctness.sh
76+
bash ./test/integration/test-api-ensemble-provider-switch.sh
77+
bash ./test/integration/test-api-ensemble-adhoc-correctness.sh
7878
bash ./test/integration/test-api-agentrun-container-shape.sh
79-
bash ./test/integration/test-api-personapack-provisioning.sh
79+
bash ./test/integration/test-api-ensemble-provisioning.sh
8080
bash ./test/integration/test-api-schedule-dispatch.sh
8181
bash ./test/integration/test-api-observability.sh
8282
bash ./test/integration/test-api-web-endpoint.sh

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ curl -fsSL https://deploy.sympozium.ai/install.sh | sh
4848
Then deploy to your cluster and activate your first agents:
4949

5050
```bash
51-
sympozium install # deploys CRDs, controllers, and built-in PersonaPacks
51+
sympozium install # deploys CRDs, controllers, and built-in Ensembles
5252
sympozium # launch the TUI — go to Personas tab, press Enter to onboard
5353
sympozium serve # open the web dashboard (port-forwards to the in-cluster UI)
5454
```
@@ -82,7 +82,7 @@ Sympozium serves **two powerful use cases** on one Kubernetes-native platform:
8282

8383
| | |
8484
|---|---|
85-
| **PersonaPacks** | Helm-like bundles for AI agent teams — activate a pack and the controller stamps out instances, schedules, and memory |
85+
| **Ensembles** | Helm-like bundles for AI agent teams — activate a pack and the controller stamps out instances, schedules, and memory |
8686
| **Agent Workflows** | Delegation, sequential pipelines, and supervision relationships between personas — visualised on an interactive canvas |
8787
| **Shared Workflow Memory** | Pack-level SQLite memory pool for cross-persona knowledge sharing with per-persona access control |
8888
| **Skill Sidecars** | Every skill runs in its own sidecar with ephemeral least-privilege RBAC, garbage-collected on completion |
@@ -103,7 +103,7 @@ Sympozium serves **two powerful use cases** on one Kubernetes-native platform:
103103
| Getting Started | [deploy.sympozium.ai/docs/getting-started](https://deploy.sympozium.ai/docs/getting-started/) |
104104
| Architecture | [deploy.sympozium.ai/docs/architecture](https://deploy.sympozium.ai/docs/architecture/) |
105105
| Custom Resources | [deploy.sympozium.ai/docs/concepts/custom-resources](https://deploy.sympozium.ai/docs/concepts/custom-resources/) |
106-
| PersonaPacks | [deploy.sympozium.ai/docs/concepts/personapacks](https://deploy.sympozium.ai/docs/concepts/personapacks/) |
106+
| Ensembles | [deploy.sympozium.ai/docs/concepts/ensembles](https://deploy.sympozium.ai/docs/concepts/ensembles/) |
107107
| Skills & Sidecars | [deploy.sympozium.ai/docs/concepts/skills](https://deploy.sympozium.ai/docs/concepts/skills/) |
108108
| Persistent Memory | [deploy.sympozium.ai/docs/concepts/persistent-memory](https://deploy.sympozium.ai/docs/concepts/persistent-memory/) |
109109
| Channels | [deploy.sympozium.ai/docs/concepts/channels](https://deploy.sympozium.ai/docs/concepts/channels/) |
@@ -117,7 +117,7 @@ Sympozium serves **two powerful use cases** on one Kubernetes-native platform:
117117
| LM Studio & Local Inference | [deploy.sympozium.ai/docs/guides/lm-studio](https://deploy.sympozium.ai/docs/guides/lm-studio/) |
118118
| llama-server | [deploy.sympozium.ai/docs/guides/llama-server](https://deploy.sympozium.ai/docs/guides/llama-server/) |
119119
| Unsloth | [deploy.sympozium.ai/docs/guides/unsloth](https://deploy.sympozium.ai/docs/guides/unsloth/) |
120-
| Writing PersonaPacks | [deploy.sympozium.ai/docs/guides/writing-personapacks](https://deploy.sympozium.ai/docs/guides/writing-personapacks/) |
120+
| Writing Ensembles | [deploy.sympozium.ai/docs/guides/writing-ensembles](https://deploy.sympozium.ai/docs/guides/writing-ensembles/) |
121121
| Your First AgentRun | [deploy.sympozium.ai/docs/guides/first-agentrun](https://deploy.sympozium.ai/docs/guides/first-agentrun/) |
122122

123123
---
Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,29 @@ import (
44
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
55
)
66

7-
// PersonaPackSpec defines a bundle of pre-configured agent personas.
8-
// Installing a PersonaPack stamps out SympoziumInstances, SympoziumSchedules,
7+
// EnsembleSpec defines a bundle of pre-configured agent personas.
8+
// Installing an Ensemble stamps out SympoziumInstances, SympoziumSchedules,
99
// and optionally seeds memory for each persona.
10-
type PersonaPackSpec struct {
11-
// Enabled controls whether the controller stamps out resources for this pack.
12-
// PersonaPacks default to disabled (catalog-only) and must be explicitly
10+
type EnsembleSpec struct {
11+
// Enabled controls whether the controller stamps out resources for this ensemble.
12+
// Ensembles default to disabled (catalog-only) and must be explicitly
1313
// activated — for example via the TUI or kubectl patch.
1414
// +optional
1515
Enabled bool `json:"enabled,omitempty"`
1616

17-
// Description is a human-readable summary of this persona pack.
17+
// Description is a human-readable summary of this ensemble.
1818
// +optional
1919
Description string `json:"description,omitempty"`
2020

21-
// Category classifies this persona pack (e.g. "platform", "security", "devops").
21+
// Category classifies this ensemble (e.g. "platform", "security", "devops").
2222
// +optional
2323
Category string `json:"category,omitempty"`
2424

25-
// Version is the persona pack version.
25+
// Version is the ensemble version.
2626
// +optional
2727
Version string `json:"version,omitempty"`
2828

29-
// Personas is the list of agent personas in this pack.
29+
// Personas is the list of agent personas in this ensemble.
3030
Personas []PersonaSpec `json:"personas"`
3131

3232
// AuthRefs references secrets containing AI provider credentials.
@@ -77,24 +77,24 @@ type PersonaPackSpec struct {
7777
ChannelAccessControl map[string]*ChannelAccessControl `json:"channelAccessControl,omitempty"`
7878

7979
// AgentSandbox configures the Kubernetes Agent Sandbox (CRD) execution backend
80-
// for all instances generated by this pack. When enabled, agent runs use Sandbox
80+
// for all instances generated by this ensemble. When enabled, agent runs use Sandbox
8181
// CRs with gVisor/Kata kernel-level isolation.
8282
// +optional
8383
AgentSandbox *AgentSandboxInstanceSpec `json:"agentSandbox,omitempty"`
8484

8585
// SharedMemory configures a shared memory pool accessible to all personas
86-
// in this pack. Each persona retains its private memory; the shared pool
86+
// in this ensemble. Each persona retains its private memory; the shared pool
8787
// provides cross-persona knowledge sharing within the workflow.
8888
// +optional
8989
SharedMemory *SharedMemorySpec `json:"sharedMemory,omitempty"`
9090

91-
// Relationships defines directed edges between personas in the pack,
91+
// Relationships defines directed edges between personas in the ensemble,
9292
// enabling coordination patterns like delegation, sequential pipelines,
9393
// and supervision.
9494
// +optional
9595
Relationships []PersonaRelationship `json:"relationships,omitempty"`
9696

97-
// WorkflowType describes the overall orchestration pattern for this pack.
97+
// WorkflowType describes the overall orchestration pattern for this ensemble.
9898
// "autonomous" (default): personas run independently on their own schedules.
9999
// "pipeline": personas execute in sequence defined by sequential edges.
100100
// "delegation": personas can actively delegate to each other at runtime.
@@ -104,7 +104,7 @@ type PersonaPackSpec struct {
104104
WorkflowType string `json:"workflowType,omitempty"`
105105
}
106106

107-
// PersonaSpec defines a single agent persona within a PersonaPack.
107+
// PersonaSpec defines a single agent persona within an Ensemble.
108108
type PersonaSpec struct {
109109
// Name is the persona identifier (used as suffix in generated instance names).
110110
Name string `json:"name"`
@@ -117,7 +117,7 @@ type PersonaSpec struct {
117117
SystemPrompt string `json:"systemPrompt"`
118118

119119
// Model overrides the default model for this persona.
120-
// If empty, the pack-level or onboarding-time model is used.
120+
// If empty, the ensemble-level or onboarding-time model is used.
121121
// +optional
122122
Model string `json:"model,omitempty"`
123123

@@ -204,9 +204,9 @@ type PersonaMemory struct {
204204
Seeds []string `json:"seeds,omitempty"`
205205
}
206206

207-
// SharedMemorySpec configures a shared memory pool for all personas in a pack.
207+
// SharedMemorySpec configures a shared memory pool for all personas in an ensemble.
208208
type SharedMemorySpec struct {
209-
// Enabled activates the shared memory server for this pack.
209+
// Enabled activates the shared memory server for this ensemble.
210210
// +kubebuilder:default=false
211211
Enabled bool `json:"enabled"`
212212

@@ -233,7 +233,7 @@ type SharedMemoryAccessRule struct {
233233
Access string `json:"access"`
234234
}
235235

236-
// PersonaRelationship defines a directed edge between two personas in a pack.
236+
// PersonaRelationship defines a directed edge between two personas in an ensemble.
237237
type PersonaRelationship struct {
238238
// Source is the persona name that initiates the interaction.
239239
Source string `json:"source"`
@@ -276,13 +276,13 @@ type InstalledPersona struct {
276276
ScheduleName string `json:"scheduleName,omitempty"`
277277
}
278278

279-
// PersonaPackStatus defines the observed state of PersonaPack.
280-
type PersonaPackStatus struct {
279+
// EnsembleStatus defines the observed state of Ensemble.
280+
type EnsembleStatus struct {
281281
// Phase is the current phase (Pending, Ready, Error).
282282
// +optional
283283
Phase string `json:"phase,omitempty"`
284284

285-
// PersonaCount is the number of personas defined in this pack.
285+
// PersonaCount is the number of personas defined in this ensemble.
286286
// +optional
287287
PersonaCount int `json:"personaCount,omitempty"`
288288

@@ -312,26 +312,26 @@ type PersonaPackStatus struct {
312312
// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase"
313313
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
314314

315-
// PersonaPack is the Schema for the personapacks API.
315+
// Ensemble is the Schema for the ensembles API.
316316
// It bundles pre-configured agent personas that can be installed to stamp out
317317
// SympoziumInstances, Schedules, and memory seeds.
318-
type PersonaPack struct {
318+
type Ensemble struct {
319319
metav1.TypeMeta `json:",inline"`
320320
metav1.ObjectMeta `json:"metadata,omitempty"`
321321

322-
Spec PersonaPackSpec `json:"spec,omitempty"`
323-
Status PersonaPackStatus `json:"status,omitempty"`
322+
Spec EnsembleSpec `json:"spec,omitempty"`
323+
Status EnsembleStatus `json:"status,omitempty"`
324324
}
325325

326326
// +kubebuilder:object:root=true
327327

328-
// PersonaPackList contains a list of PersonaPack.
329-
type PersonaPackList struct {
328+
// EnsembleList contains a list of Ensemble.
329+
type EnsembleList struct {
330330
metav1.TypeMeta `json:",inline"`
331331
metav1.ListMeta `json:"metadata,omitempty"`
332-
Items []PersonaPack `json:"items"`
332+
Items []Ensemble `json:"items"`
333333
}
334334

335335
func init() {
336-
SchemeBuilder.Register(&PersonaPack{}, &PersonaPackList{})
336+
SchemeBuilder.Register(&Ensemble{}, &EnsembleList{})
337337
}

0 commit comments

Comments
 (0)