Skip to content

feat(agents): multi-agent personas with per-agent identity and memory#97

Open
penso wants to merge 7 commits intomainfrom
how-to-build-agents
Open

feat(agents): multi-agent personas with per-agent identity and memory#97
penso wants to merge 7 commits intomainfrom
how-to-build-agents

Conversation

@penso
Copy link
Collaborator

@penso penso commented Feb 12, 2026

Summary

  • Add named agent personas — each with its own identity (name, emoji, creature, vibe), soul/system prompt, workspace directory, and memory store
  • Sessions can be assigned to a specific agent via the UI header dropdown or the Telegram /agent command
  • The "main" agent maps to the existing root-level workspace so no file migration is needed
  • Feature-gated behind agent cargo feature (enabled by default in CLI)

What's included

Area Changes
Store AgentPersonaStore with SQLite CRUD + unit tests
Config Per-agent path/load/save functions (identity, soul, workspace)
Prompt Agent-aware prompt assembly in chat.rs
Memory Per-agent MemoryManager lazily created in state.rs
RPC agents.* CRUD + agents.identity.* + agents.set_session
UI Settings > Agents page, session header selector, sidebar emoji badges
Telegram /agent command to list/switch agents
Migrations agents table + session.agent_id column
E2E agents.spec.js + updated settings-nav.spec.js

Validation

Completed

  • cargo build — passes
  • cargo test — all tests pass (0 failures)
  • just format-check — clean
  • cargo clippy --all-targets — clean
  • biome ci crates/gateway/src/assets/js/ — clean (0 errors)
  • biome check --write on new JS files — applied

Remaining

  • E2E tests: cd crates/gateway/ui && npx playwright test e2e/specs/agents.spec.js
  • Manual QA: create agent, assign to session, verify prompt changes
  • just release-preflight (blocked by pre-existing CUDA Toolkit requirement on this machine)

Manual QA

  1. Navigate to Settings > Agents — verify main agent card with "Default" badge
  2. Create a new agent with name/emoji/soul
  3. Open chat, use agent selector dropdown to assign session
  4. Verify agent's identity appears in system prompt
  5. Delete agent — verify session falls back to main

…mory

Enable named agent personas — each with its own identity (name, emoji,
creature, vibe), soul/system prompt, workspace directory, and memory store.
Sessions can be assigned to an agent via the UI header dropdown or the
Telegram /agent command. The "main" agent maps to the existing root-level
workspace, so no file migration is needed.

Feature-gated behind `agent` (enabled by default in CLI).

New files:
- agent_persona.rs: AgentPersonaStore with SQLite CRUD + unit tests
- page-agents.js: Settings > Agents page (create/edit/delete agents)
- agents.spec.js: E2E tests for the agents settings page
- Two SQL migrations (agents table + session agent_id column)

Key changes:
- Per-agent config loader functions (identity, soul, workspace paths)
- Agent-aware prompt assembly in chat.rs
- Per-agent memory managers (lazily created) in state.rs
- Agent-scoped identity RPC methods (get/update/update_soul)
- Session agent selector in header + emoji badges in sidebar
- /agent command for Telegram channels
Adds a new icon-user-group CSS class (Heroicons user-group outline)
and uses it for the Settings > Agents sidebar item so it's visually
distinct from the Identity (single person) icon.
Replace the plain text input for agent emoji with the shared EmojiPicker
component (same as Identity page). Move the New Agent button inline next
to the heading to match other settings pages.
The agents page mounts and calls sendRpc before the WebSocket is
assigned to S.ws, causing an immediate "WebSocket not connected"
error. Add the same retry-with-backoff pattern used by other pages
(up to 30 attempts at 200ms intervals).
When creating a new agent, fetch the main agent's soul via
agents.identity.get and use it as the default value for the soul
textarea, so new agents start with the same base personality.
The AgentForm useEffect that loads the soul (main's SOUL.md for new
agents) also races with WebSocket initialization. Add the same retry
pattern so the soul textarea gets pre-filled reliably.
The description field adds clutter without enough value — agent
id/name is sufficient. The DB column is kept for backwards compat
but the UI no longer sends or displays it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments