From 3f354c0432e476f8c322b87b0da291cce5869207 Mon Sep 17 00:00:00 2001 From: James Pine Date: Tue, 3 Mar 2026 23:55:40 -0800 Subject: [PATCH 01/15] =?UTF-8?q?feat:=20agent=20factory=20=E2=80=94=20pre?= =?UTF-8?q?set=20system,=20factory=20tools,=20and=20cortex=20integration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement the Agent Factory: a conversational system for creating, configuring, and refining agents through presets and LLM-callable tools. Phase 0 — Deprecate USER.md: - Add description field to HumanDef for rich human context on the org graph - Remove user field from Identity, stop loading/scaffolding USER.md - Rewrite build_org_context() to render human roles and descriptions - Update API types, human CRUD handlers, dashboard UI Phase 1 — Preset system: - 9 embedded preset archetypes (8 specialists + main-agent) in presets/ - PresetRegistry using rust-embed with list/load API - API endpoints: GET /api/factory/presets, GET /api/factory/presets/:id - 5 unit tests Phase 2 — Factory tools (6 LLM-callable tools): - factory_list_presets, factory_load_preset, factory_search_context - factory_create_agent (full lifecycle: create + identity files + org links) - factory_update_identity, factory_update_config (refinement) - Extracted create_agent_internal() from API handler for tool reuse Phase 3 — Factory prompt: - prompts/en/factory.md.j2 with creation flow, soul writing guide, synthesis rules Phase 5 — Cortex chat integration: - Factory tools wired into cortex chat via add_factory_tools() - Conditional Agent Factory section in cortex_chat.md.j2 Phase 6 — Polish: - Fix LinkSpec schema/parser mismatch (critical: direction/kind enum values) - Agent ID format validation (lowercase, hyphens, 2-64 chars) - Identity content non-empty validation in create and update tools - Model routing provider validation in factory_update_config - Tuning value range validation (branches 1-32, workers 1-64, etc.) - Clamp max_results in factory_search_context (1-25) - Best-effort identity file writes with error reporting - Add config_write_mutex to ApiState for safe read-modify-write cycles --- docs/design-docs/agent-factory.md | 502 ++++++++++++++++++ interface/src/api/client.ts | 5 +- interface/src/components/TopologyGraph.tsx | 29 +- interface/src/routes/AgentConfig.tsx | 13 +- interface/src/routes/AgentDetail.tsx | 5 +- presets/community-manager/IDENTITY.md | 18 + presets/community-manager/ROLE.md | 30 ++ presets/community-manager/SOUL.md | 34 ++ presets/community-manager/meta.toml | 9 + presets/content-writer/IDENTITY.md | 18 + presets/content-writer/ROLE.md | 32 ++ presets/content-writer/SOUL.md | 34 ++ presets/content-writer/meta.toml | 9 + presets/customer-support/IDENTITY.md | 18 + presets/customer-support/ROLE.md | 34 ++ presets/customer-support/SOUL.md | 35 ++ presets/customer-support/meta.toml | 9 + presets/engineering-assistant/IDENTITY.md | 18 + presets/engineering-assistant/ROLE.md | 38 ++ presets/engineering-assistant/SOUL.md | 34 ++ presets/engineering-assistant/meta.toml | 9 + presets/executive-assistant/IDENTITY.md | 18 + presets/executive-assistant/ROLE.md | 38 ++ presets/executive-assistant/SOUL.md | 32 ++ presets/executive-assistant/meta.toml | 9 + presets/main-agent/IDENTITY.md | 18 + presets/main-agent/ROLE.md | 35 ++ presets/main-agent/SOUL.md | 40 ++ presets/main-agent/meta.toml | 9 + presets/project-manager/IDENTITY.md | 19 + presets/project-manager/ROLE.md | 37 ++ presets/project-manager/SOUL.md | 32 ++ presets/project-manager/meta.toml | 9 + presets/research-analyst/IDENTITY.md | 18 + presets/research-analyst/ROLE.md | 31 ++ presets/research-analyst/SOUL.md | 32 ++ presets/research-analyst/meta.toml | 9 + presets/sales-bdr/IDENTITY.md | 19 + presets/sales-bdr/ROLE.md | 41 ++ presets/sales-bdr/SOUL.md | 35 ++ presets/sales-bdr/meta.toml | 9 + prompts/en/cortex_chat.md.j2 | 22 + prompts/en/factory.md.j2 | 166 ++++++ prompts/en/fragments/org_context.md.j2 | 15 +- .../factory_create_agent_description.md.j2 | 1 + .../factory_list_presets_description.md.j2 | 1 + .../factory_load_preset_description.md.j2 | 1 + .../factory_search_context_description.md.j2 | 1 + .../factory_update_config_description.md.j2 | 1 + .../factory_update_identity_description.md.j2 | 1 + prompts/en/tools/file_description.md.j2 | 2 +- prompts/en/worker.md.j2 | 2 +- src/agent/channel.rs | 33 +- src/agent/cortex_chat.rs | 10 + src/api.rs | 3 +- src/api/agents.rs | 119 +++-- src/api/factory.rs | 24 + src/api/links.rs | 23 + src/api/server.rs | 8 +- src/api/state.rs | 4 + src/config/load.rs | 3 + src/config/toml_schema.rs | 1 + src/config/types.rs | 3 + src/config/watcher.rs | 2 +- src/factory.rs | 5 + src/factory/presets.rs | 181 +++++++ src/identity.rs | 2 +- src/identity/files.rs | 16 +- src/lib.rs | 4 + src/main.rs | 21 +- src/prompts/engine.rs | 28 + src/prompts/text.rs | 19 + src/tools.rs | 76 +++ src/tools/factory_create_agent.rs | 430 +++++++++++++++ src/tools/factory_list_presets.rs | 85 +++ src/tools/factory_load_preset.rs | 96 ++++ src/tools/factory_search_context.rs | 201 +++++++ src/tools/factory_update_config.rs | 433 +++++++++++++++ src/tools/factory_update_identity.rs | 186 +++++++ src/tools/file.rs | 2 +- tests/bulletin.rs | 1 + tests/context_dump.rs | 5 +- 82 files changed, 3559 insertions(+), 101 deletions(-) create mode 100644 docs/design-docs/agent-factory.md create mode 100644 presets/community-manager/IDENTITY.md create mode 100644 presets/community-manager/ROLE.md create mode 100644 presets/community-manager/SOUL.md create mode 100644 presets/community-manager/meta.toml create mode 100644 presets/content-writer/IDENTITY.md create mode 100644 presets/content-writer/ROLE.md create mode 100644 presets/content-writer/SOUL.md create mode 100644 presets/content-writer/meta.toml create mode 100644 presets/customer-support/IDENTITY.md create mode 100644 presets/customer-support/ROLE.md create mode 100644 presets/customer-support/SOUL.md create mode 100644 presets/customer-support/meta.toml create mode 100644 presets/engineering-assistant/IDENTITY.md create mode 100644 presets/engineering-assistant/ROLE.md create mode 100644 presets/engineering-assistant/SOUL.md create mode 100644 presets/engineering-assistant/meta.toml create mode 100644 presets/executive-assistant/IDENTITY.md create mode 100644 presets/executive-assistant/ROLE.md create mode 100644 presets/executive-assistant/SOUL.md create mode 100644 presets/executive-assistant/meta.toml create mode 100644 presets/main-agent/IDENTITY.md create mode 100644 presets/main-agent/ROLE.md create mode 100644 presets/main-agent/SOUL.md create mode 100644 presets/main-agent/meta.toml create mode 100644 presets/project-manager/IDENTITY.md create mode 100644 presets/project-manager/ROLE.md create mode 100644 presets/project-manager/SOUL.md create mode 100644 presets/project-manager/meta.toml create mode 100644 presets/research-analyst/IDENTITY.md create mode 100644 presets/research-analyst/ROLE.md create mode 100644 presets/research-analyst/SOUL.md create mode 100644 presets/research-analyst/meta.toml create mode 100644 presets/sales-bdr/IDENTITY.md create mode 100644 presets/sales-bdr/ROLE.md create mode 100644 presets/sales-bdr/SOUL.md create mode 100644 presets/sales-bdr/meta.toml create mode 100644 prompts/en/factory.md.j2 create mode 100644 prompts/en/tools/factory_create_agent_description.md.j2 create mode 100644 prompts/en/tools/factory_list_presets_description.md.j2 create mode 100644 prompts/en/tools/factory_load_preset_description.md.j2 create mode 100644 prompts/en/tools/factory_search_context_description.md.j2 create mode 100644 prompts/en/tools/factory_update_config_description.md.j2 create mode 100644 prompts/en/tools/factory_update_identity_description.md.j2 create mode 100644 src/api/factory.rs create mode 100644 src/factory.rs create mode 100644 src/factory/presets.rs create mode 100644 src/tools/factory_create_agent.rs create mode 100644 src/tools/factory_list_presets.rs create mode 100644 src/tools/factory_load_preset.rs create mode 100644 src/tools/factory_search_context.rs create mode 100644 src/tools/factory_update_config.rs create mode 100644 src/tools/factory_update_identity.rs diff --git a/docs/design-docs/agent-factory.md b/docs/design-docs/agent-factory.md new file mode 100644 index 000000000..d28f5b4eb --- /dev/null +++ b/docs/design-docs/agent-factory.md @@ -0,0 +1,502 @@ +# Agent Factory + +A natural-language-driven system for creating, configuring, and refining agents. The main agent (or cortex chat) guides the user through agent creation using conversational questions, preset soul archetypes, and the main agent's existing memories — producing fully configured agents with rich identity files, appropriate model routing, org links, and platform bindings. + +## Problem + +Creating a new agent today requires: +1. Give it a name and ID (the only thing the UI captures) +2. Manually write SOUL.md, IDENTITY.md, USER.md, ROLE.md from scratch +3. Edit config.toml to set routing, tuning, and platform bindings +4. Create links to other agents in the topology +5. Understand the architecture well enough to make good choices + +There are no presets, no guidance on writing a soul, no way to leverage existing context. Most users give up after step 1 and end up with a blank agent that doesn't know who it is. + +## Solution + +The factory is a guided creation flow where the user describes what they want in natural language. The system synthesizes a fully configured agent from three sources: + +1. **User intent** — conversational answers about what the agent should do, how it should communicate, what platforms it should be on +2. **Preset archetypes** — 8 curated soul/identity/role templates that serve as starting material for synthesis (never used directly) +3. **Main agent's memories** — searched at creation time for company context, domain knowledge, preferences, organizational structure + +The factory is not a form. It's a conversation with the agent that happens to produce another agent. + +--- + +## Phase 0: Deprecate USER.md — Humans Own Their Context + +### Motivation + +USER.md is a per-agent file that describes "the human this agent interacts with." This made sense for single-agent setups, but breaks down in multi-agent orgs: + +- Every agent needs its own copy of USER.md, manually maintained +- There's no way to have multiple humans interact with multiple agents without duplicating context everywhere +- The org graph already has `[[humans]]` nodes with `display_name`, `role`, and `bio`, but this data is completely disconnected from USER.md +- `build_org_context()` doesn't even use the human's `display_name` — it falls back to the raw id (e.g., "admin") + +The fix: human context belongs to the human node in the org graph. When a human is linked to an agent, the agent inherits that human's description in its system prompt. USER.md becomes unnecessary. + +### Changes + +#### 1. Add `description` field to `HumanDef` + +The existing `bio` field is a short 2-3 sentence blurb for the topology UI. The new `description` field is the rich, long-form equivalent of what USER.md was — paragraphs of context about the person (preferences, background, communication style, timezone, etc.). + +```rust +// config.rs +pub struct HumanDef { + pub id: String, + pub display_name: Option, + pub role: Option, + pub bio: Option, + pub description: Option, // NEW — replaces USER.md +} +``` + +TOML representation: + +```toml +[[humans]] +id = "jamie" +display_name = "Jamie Pine" +role = "Founder" +bio = "Creator of Spacebot and Spacedrive." +description = """ +Jamie Pine (@jamiepine). Timezone: America/Vancouver. + +Full-stack developer, open source maintainer. Created Spacedrive (cross-platform +file manager) and Spacebot (agentic AI system). Works in Rust and TypeScript. + +Streams development on Twitch. Prefers direct, concise communication. Comfortable +with technical depth. Uses AI tools extensively in his workflow. +""" +``` + +#### 2. Propagate human descriptions into org_context + +Currently `build_org_context()` creates `LinkedAgent { name, id, is_human }` structs and the template only shows the name. This needs to: + +a. Look up the `HumanDef` for linked humans (not just negative-lookup against `agent_names`) +b. Use `display_name` for the human's name (falling back to id) +c. Pass `description` (and `role`, `bio`) through to the template + +New template data: + +```rust +// engine.rs +pub struct LinkedEntity { + pub name: String, // display_name or id + pub id: String, + pub is_human: bool, + pub role: Option, + pub description: Option, // human description, injected into prompt +} +``` + +Updated org_context.md.j2 fragment: + +```jinja2 +{% if entry.is_human -%} +- **{{ entry.name }}** (human){% if entry.role %} — {{ entry.role }}{% endif %} +{% if entry.description %} +{{ entry.description }} +{% endif %} +{% else -%} +- **{{ entry.name }}** — ... +{% endif -%} +``` + +This means: when a human is linked to an agent, the agent's system prompt includes that human's full description in the Organization section. Multiple humans linked to the same agent all appear. The agent knows who it's working with based on the org graph, not a static file. + +#### 3. Deprecate USER.md loading + +- `Identity::load()` stops loading USER.md (set `user: None` unconditionally) +- `Identity::render()` stops rendering the `## User` section +- `scaffold_identity_files()` stops creating USER.md for new agents +- The file tool's `PROTECTED_FILES` list removes USER.md +- If a USER.md file exists on disk, it is ignored (not deleted — just not loaded) + +#### 4. Startup migration for existing users + +On startup, after config is loaded but before agents are initialized: + +1. **For each agent with a non-empty USER.md in its workspace:** + - Read the content of `workspace/USER.md` + - If there is exactly one human in the config (the default "admin"), set its `description` to the USER.md content + - If there are multiple humans, log a warning: "USER.md found for agent '{id}' but multiple humans exist. Please manually assign the content to the appropriate human's description." + - Rename the file to `USER.md.deprecated` so it's preserved but no longer loaded + +2. **Auto-link the default human to the main agent:** + - If there is a human with no links to any agent, create a hierarchical link from that human to the default agent (the human is the superior — they are the owner) + - This only runs on first migration — once links exist, it doesn't touch them + +3. **Persist changes:** + - Write the updated `[[humans]]` with `description` to config.toml + - Write the new `[[links]]` entry to config.toml + +#### 5. Default human creation with auto-link + +Currently, if no `[[humans]]` entries exist, a bare "admin" human is created at config parse time. Extend this: + +- Still create the default "admin" human +- Also create a default link: `from = "admin"`, `to = "{default_agent_id}"`, `direction = "two_way"`, `kind = "hierarchical"` +- This ensures new installations start with the human connected to their main agent + +#### 6. API updates + +- `CreateHumanRequest` and `UpdateHumanRequest` gain a `description: Option` field +- `TopologyHuman` response includes `description` +- `GET /api/agents/identity` and `PUT /api/agents/identity` drop the `user` field (breaking change, but the field becomes meaningless) +- Add a deprecation note to the API: `user` field in identity endpoints is ignored + +#### 7. Dashboard UI updates + +- `HumanEditDialog` in TopologyGraph.tsx gets a new `description` textarea (larger than `bio`, with a label like "Full context — background, preferences, communication style") +- The agent config identity tab (`AgentConfig.tsx`) removes the USER.md tab +- The agent detail overview (`AgentDetail.tsx`) removes the USER.md preview tab + +#### 8. Humans lookup in build_org_context + +`AgentDeps` or the channel needs access to the humans list to look up descriptions. Options: + +a. Add `humans: Arc>>` to `AgentDeps` (already exists as `state.agent_humans` in the API layer — pass it through) +b. Build a `HashMap` at startup for O(1) lookup + +The channel's `build_org_context()` then: +- For each linked node, checks `agent_names` (is it an agent?) then `humans_map` (is it a human?) +- For humans: uses `display_name.unwrap_or(id)` for the name, passes `role` and `description` through + +--- + +## Phase 1: Preset System + +### Preset Structure + +Eight preset archetypes ship embedded in the binary. Each is a directory of markdown files: + +``` +presets/ + community-manager/ + SOUL.md + IDENTITY.md + ROLE.md + meta.toml + research-analyst/ + customer-support/ + engineering-assistant/ + content-writer/ + sales-bdr/ + executive-assistant/ + project-manager/ +``` + +#### meta.toml + +```toml +id = "community-manager" +name = "Community Manager" +description = "Engages with community members, moderates discussions, answers FAQs, and keeps the vibe positive." +icon = "users" +tags = ["discord", "slack", "community", "moderation", "support"] + +[defaults] +max_concurrent_workers = 3 +max_turns = 5 +``` + +Note: model routing is intentionally excluded from presets. Presets are provider-agnostic — model selection happens during the factory conversation when the user's available providers are known. + +#### Presets + +| Preset | Description | +|--------|-------------| +| Community Manager | Discord/Slack engagement, moderation, FAQ handling | +| Research Analyst | Deep research, document synthesis, report generation | +| Customer Support | Ticket triage, escalation, empathetic communication | +| Engineering Assistant | Code review, architecture, PR management, technical docs | +| Content Writer | Blog posts, docs, social media, consistent voice | +| Sales / BDR | Lead qualification, outreach drafting, follow-ups | +| Executive Assistant | Email drafting, meeting prep, information synthesis | +| Project Manager | Task tracking, status updates, cross-team coordination | + +#### Embedding + +Presets are compiled into the binary via `include_dir!`: + +```rust +impl PresetRegistry { + fn list() -> Vec; + fn load(id: &str) -> Option; +} + +struct Preset { + meta: PresetMeta, + soul: String, + identity: String, + role: String, +} +``` + +#### API + +``` +GET /api/factory/presets → Vec +GET /api/factory/presets/:id → Preset (full content) +``` + +### Files + +- `presets/` directory with 8 archetype subdirectories +- `src/factory/mod.rs` — module root +- `src/factory/presets.rs` — `PresetRegistry`, `Preset`, `PresetMeta`, `include_dir!` loading +- `src/api/factory.rs` — preset listing/loading endpoints + +--- + +## Phase 2: Factory Tools + +Six new LLM-callable tools: + +| Tool | Purpose | +|------|---------| +| `factory_list_presets` | Lists available archetypes with metadata | +| `factory_load_preset` | Loads a preset's full content (soul, identity, role, defaults) | +| `factory_search_context` | Searches the main agent's memories for relevant context | +| `factory_create_agent` | Creates a fully configured agent — calls create API, writes identity files, creates links | +| `factory_update_identity` | Updates identity files for any agent (refinement) | +| `factory_update_config` | Updates routing/tuning config for any agent | + +`factory_create_agent` takes a complete specification: + +```rust +struct FactoryCreateAgentArgs { + agent_id: String, + display_name: String, + role: String, + soul_content: String, + identity_content: String, + role_content: String, + routing: Option, + links: Vec, +} +``` + +Note: no `user_content` — human context now flows through org links, not identity files. + +### Files + +- `src/tools/factory_list_presets.rs` +- `src/tools/factory_load_preset.rs` +- `src/tools/factory_search_context.rs` +- `src/tools/factory_create_agent.rs` +- `src/tools/factory_update_identity.rs` +- `src/tools/factory_update_config.rs` +- `src/factory/synthesis.rs` — shared logic for identity file generation, preset merging +- `tools.rs` — `factory_tool_server()` function + +--- + +## Phase 3: Factory Prompt + +A dedicated template (`prompts/en/factory.md.j2`) that instructs the LLM on how to be an agent factory: + +1. **What you're doing** — Creating a new agent in a multi-agent system. You have tools to load presets, search memories, and create agents. +2. **How agents work** — Soul/identity/role system, what each file controls, how agents link, routing/tuning options. +3. **The creation flow** — Step-by-step: understand intent → search memories → present presets → ask about personality → ask about platforms → ask about org position → synthesize → summarize → create → offer refinement. +4. **Soul writing guide** — How to write effective souls. Voice, boundaries, judgment. Preset examples as reference. +5. **Synthesis rules** — Presets are starting material, not templates. Always customize. Inject organizational context from memory search. Match existing org communication style. + +### Files + +- `prompts/en/factory.md.j2` +- `src/prompts/engine.rs` — `render_factory_prompt()` +- `src/prompts/text.rs` — register template + +--- + +## Phase 4: Structured Message Types + +New generic message primitives for interactive chat components, reusable by any feature. + +### Schema + +Messages gain an optional `structured` field: + +```rust +struct StructuredContent { + kind: StructuredKind, +} + +enum StructuredKind { + /// Clickable options. User picks one (or types custom). + Buttons { + prompt: String, + buttons: Vec, + }, + /// Card grid for preset selection. Visual, with descriptions. + SelectCards { + prompt: String, + cards: Vec, + allow_multiple: bool, + }, + /// Step progress indicator. + Progress { + steps: Vec, + current: usize, + }, + /// Summary card with key-value pairs and action buttons. + Summary { + title: String, + fields: Vec<(String, String)>, + actions: Vec, + }, +} + +struct ButtonOption { + label: String, + value: String, // injected as user message when clicked + description: Option, + icon: Option, +} + +struct SelectCard { + id: String, + title: String, + description: String, + icon: Option, + tags: Vec, +} + +struct ProgressStep { + label: String, + status: StepStatus, // Pending | Active | Done | Error +} +``` + +### Transport + +Outbound SSE events include an optional `structured` JSON field. The frontend renders the appropriate component. When the user clicks a button or card, the frontend injects the `value` as a regular user message. No bidirectional widget protocol — the agent controls the flow through tool calls. + +### Frontend Components + +New components in `interface/src/components/structured/`: + +- `ChatButtons.tsx` — button group +- `CardSelect.tsx` — selectable card grid with icon, title, description, tags +- `ProgressSteps.tsx` — horizontal step indicator +- `SummaryCard.tsx` — key-value summary with action buttons + +Integrated into both `WebChatPanel` and `CortexChatPanel`. + +### Files (Rust) + +- `src/api/types.rs` or inline — `StructuredContent`, `StructuredKind`, serde +- Extend `ApiEvent::OutboundMessage` with optional `structured` field +- Extend `webchat.rs` and `cortex.rs` SSE payloads + +### Files (TypeScript) + +- `interface/src/api/client.ts` — extend types +- `interface/src/components/structured/ChatButtons.tsx` +- `interface/src/components/structured/CardSelect.tsx` +- `interface/src/components/structured/ProgressSteps.tsx` +- `interface/src/components/structured/SummaryCard.tsx` +- `WebChatPanel.tsx` and `CortexChatPanel.tsx` — render structured content + +--- + +## Phase 5: Factory Integration + +### Entry Points + +Both paths converge on the same backend: + +**Portal webchat (main agent):** User says "create me a support agent" in chat. The channel detects factory intent and delegates to a factory branch with factory tools + memory tools + the factory system prompt. + +**Cortex chat:** Factory tools are added to the cortex chat tool server. Same conversational flow, same backend. + +### Creation Flow + +``` +User: "I need an agent that handles customer support tickets from email" + +Agent: [branch → factory_search_context("company info", "support process")] + [branch → factory_list_presets()] + +Agent: "Found context about your company. Here are starting points:" + [structured: SelectCards — Customer Support, Community Manager, + Executive Assistant, with relevance tags] + +User: [clicks Customer Support] + +Agent: [branch → factory_load_preset("customer-support")] + "How should this agent communicate?" + [structured: Buttons — "Professional & formal", "Friendly & warm", + "Match the customer's tone", "Same as {main_agent}"] + +User: "Friendly but professional. We're a dev tools company." + +Agent: "Should it handle everything or escalate some things?" + [structured: Buttons — "Handle everything", "Escalate billing/refunds", + "Escalate complex issues", "Custom rules"] + +User: "Escalate billing, refunds, and anything legal." + +Agent: "Where does it fit in the org?" + [structured: Buttons — "Reports to main", "Peer of main", + "Independent"] + +User: [clicks "Reports to main"] + +Agent: [factory_create_agent with synthesized identity files] + [structured: Summary — ID, role, personality, escalation rules, + model, org position, with "Refine" and "Looks good" buttons] + +User: "Looks good!" + +Agent: "support is live. Route email to it from Settings > Bindings." +``` + +### Refinement + +After creation, or for existing agents: + +``` +User: "make the support agent more casual" +Agent: [reads current SOUL.md → rewrites with casual voice → factory_update_identity] + "Updated. More relaxed tone, still precise on technical stuff." +``` + +### Files + +- `src/agent/channel.rs` — factory intent detection, factory branch spawning +- `src/agent/cortex_chat.rs` — factory mode for cortex chat +- `src/factory/flow.rs` — shared orchestration logic (if needed) + +--- + +## Phase 6: Polish & Testing + +- Integration tests for the full factory flow +- Error handling / rollback if creation fails mid-flow +- Edge cases: duplicate IDs, hosted agent limits, permissions +- UI polish: animations, loading states, error display +- Documentation updates + +--- + +## Open Questions + +1. **Factory as a skill?** Could the factory prompt and tools be packaged as a built-in skill? Keeps it modular and consistent with the skills system. + +2. **Binding creation:** Should the factory also handle setting up platform bindings (e.g., "route emails from support@company.com to this agent")? + +3. **Agent cloning:** Should there be a "clone this agent" shortcut? + +4. **Preset contributions:** V2 could allow users to export agent configs as presets and share via registry (like skills.sh). + +5. **Memory seeding:** Should the factory optionally copy a subset of the main agent's memories to the new agent? + +6. **Structured content in other adapters:** Discord/Slack both support rich embeds and buttons. Map structured types to platform-native components in V2? diff --git a/interface/src/api/client.ts b/interface/src/api/client.ts index 482d056d1..d1ed87e1b 100644 --- a/interface/src/api/client.ts +++ b/interface/src/api/client.ts @@ -495,14 +495,12 @@ export type CortexChatSSEEvent = export interface IdentityFiles { soul: string | null; identity: string | null; - user: string | null; } export interface IdentityUpdateRequest { agent_id: string; soul?: string | null; identity?: string | null; - user?: string | null; } // -- Agent Config Types -- @@ -1202,6 +1200,7 @@ export interface TopologyHuman { display_name?: string; role?: string; bio?: string; + description?: string; } export interface TopologyResponse { @@ -1216,12 +1215,14 @@ export interface CreateHumanRequest { display_name?: string; role?: string; bio?: string; + description?: string; } export interface UpdateHumanRequest { display_name?: string; role?: string; bio?: string; + description?: string; } export interface CreateGroupRequest { diff --git a/interface/src/components/TopologyGraph.tsx b/interface/src/components/TopologyGraph.tsx index aac095aa9..0e0576a95 100644 --- a/interface/src/components/TopologyGraph.tsx +++ b/interface/src/components/TopologyGraph.tsx @@ -538,10 +538,10 @@ function EdgeConfigPanel({ // -- Human Edit Dialog -- interface HumanEditDialogProps { - human: { id: string; display_name?: string; role?: string; bio?: string } | null; + human: { id: string; display_name?: string; role?: string; bio?: string; description?: string } | null; open: boolean; onOpenChange: (open: boolean) => void; - onUpdate: (displayName: string, role: string, bio: string) => void; + onUpdate: (displayName: string, role: string, bio: string, description: string) => void; onDelete: () => void; } @@ -555,6 +555,7 @@ function HumanEditDialog({ const [displayName, setDisplayName] = useState(""); const [role, setRole] = useState(""); const [bio, setBio] = useState(""); + const [description, setDescription] = useState(""); // Sync state when a different human is selected const prevId = useRef(null); @@ -563,13 +564,14 @@ function HumanEditDialog({ setDisplayName(human.display_name ?? ""); setRole(human.role ?? ""); setBio(human.bio ?? ""); + setDescription(human.description ?? ""); } if (!human) return null; return ( - + Edit Human @@ -599,10 +601,21 @@ function HumanEditDialog({ value={bio} onChange={(e) => setBio(e.target.value)} placeholder="A short description..." - rows={3} + rows={2} className="w-full rounded-md bg-app-input px-3 py-2 text-sm text-ink outline-none border border-app-line/50 focus:border-accent/50 resize-none" /> +
+ +

Background, preferences, communication style, timezone. Agents linked to this human will see this in their system prompt.

+