Appearance
Stage 3a: Embryo 🧬
Axiom gains the power to create new agents and assign skills dynamically. The organism begins to build itself through conversation.
Status: ✅ Complete Tests: 49/49 passing Focus: Self-building via add_agent + add_skill_to_agent
What This Stage Unlocks
For the first time, the organism can grow itself. Axiom can:
- Create new agents (with their own folders, DNA, instructions)
- Assign library skills to those agents
- Delegate tasks to them synchronously
- List what exists (agents + available catalog skills)
The user talks to Axiom, Axiom builds the specialist agents needed for that domain. No developer involvement.
The Framework/Tenant Separation
orbita-core/
├── agents/ ← FRAMEWORK (ships with Orbita)
│ └── axiom/ Only built-in agent
│
├── tenant/ ← CUSTOMER'S SPACE
│ ├── README.md
│ └── agents/ Dynamic agents Axiom creates go here
│ └── <your-agent>/
│
├── dna.md (Framework — genetic code)
├── skills/ (Framework — markdown skills)
└── src/ (Framework — code)Why split?
- Framework updates don't touch customer's agents
- Customers can
.gitignore tenant/OR commit their organism - Export/share tenant folder to back up or recreate
Runtime treats them as ONE organism — same heartbeat, same inbox, same database. The separation is physical (disk) not logical.
New Components
1. Skill Catalog (src/genesis/skill-catalog.ts)
A central registry of all library skills. Each entry knows:
- Name
- Description
- Whether it's structural (BUILD-mode only, enforced in 3b)
- How to instantiate it (factory function)
typescript
catalog.register({
name: "add_contact",
description: "Add a person to the organization",
structural: true,
create: addContactFactory, // (ctx) => SkillDefinition
});2. Agent Registry (src/genesis/agent-registry.ts)
MongoDB collection tracking dynamic agents:
typescript
{
name: "contact-manager",
instruction: "You handle contacts...",
skills: ["add_contact", "query_org", "send_message"],
createdBy: "axiom",
createdAt: "2026-04-05T..."
}3. Four New Axiom Tools
| Tool | What It Does |
|---|---|
add_agent | Creates agent folder in tenant/agents/, writes DNA + instruction, registers in DB |
add_skill_to_agent | Assigns a library skill to an existing agent |
list_agents | Shows all agents + their skills + what's available in catalog |
delegate_to_agent | Synchronously invokes another agent with a message |
4. New Library Skill
add_contact— Add a person to the organization. Demonstrates the full flow.
The Self-Building Flow
User: "Create an agent called contact-manager to handle adding
and looking up contacts. Give it add_contact and query_org skills."
Axiom:
1. Calls add_agent(
name="contact-manager",
instruction="You are the contact manager. You add and look up people...",
initial_skills=["add_contact", "query_org", "send_message"]
)
2. Creates: tenant/agents/contact-manager/
├── dna.md
├── instruction.md
└── skills/
3. Registers in MongoDB: { name, instruction, skills, createdBy: "axiom" }
4. Responds: "Created contact-manager with 3 skills."
User: "Add Merlin, phone 9447774135, role Assistant, language English"
Axiom:
1. Calls list_agents → sees contact-manager with add_contact skill
2. Calls delegate_to_agent("contact-manager", "Add Merlin, phone...")
3. contact-manager wakes with its 3 skills available
4. contact-manager calls add_contact(name="Merlin", role="Assistant", ...)
5. Merlin saved to contacts collection
6. contact-manager responds: "Contact added: Merlin (Assistant)"
7. Axiom relays to user: "Done. Merlin is in the organization."Architecture Diagram
┌─────────────────────────────────────────────────┐
│ /talk UI │
└────────────────────────┬────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ AXIOM (framework) │
│ Skills: add_agent, add_skill_to_agent, │
│ list_agents, delegate_to_agent, │
│ add_contact, send_message, ... │
└──────┬───────────────────────────┬──────────────┘
│ │
delegates to creates via
│ add_agent
▼ │
┌────────────────────┐ │
│ Tenant Agent │◄────────────┘
│ (in tenant/) │
│ │
│ Has subset of │
│ catalog skills │
└─────┬──────────────┘
│
▼
┌────────────────────────────────────────────────┐
│ SHARED SERVICES (one per organism) │
│ - Org (contacts) │
│ - Inbox │
│ - Scheduler │
│ - State │
│ - Agent Registry │
│ - Catalog │
└────────────────────────────────────────────────┘Key Files
| File | Purpose |
|---|---|
src/genesis/skill-catalog.ts | Catalog class + skill context types |
src/genesis/agent-registry.ts | MongoDB registry for dynamic agents |
src/genesis/build-catalog.ts | Wires all library skills into the catalog |
src/tools/add-agent.skill.ts | Structural: creates agent folders + DB entries |
src/tools/add-skill-to-agent.skill.ts | Structural: assigns skills |
src/tools/list-agents.skill.ts | Introspection |
src/tools/delegate-to-agent.skill.ts | Synchronous agent invocation |
src/tools/add-contact.skill.ts | Library: add person to org |
src/tools/factories.ts | Thin wrappers: SkillContext → SkillDefinition |
tenant/agents/ | Where dynamic agents live on disk |
Tests Added
test/agent-registry.test.ts(9 tests) — registry CRUDtest/catalog.test.ts(3 tests) — catalog wiring
Combined with existing tests: 49/49 passing
What's Still Missing (Stages 3b + 3c)
Stage 3b: Build/Fuse mode + governance
- System-wide mode flag
- Structural tools only allowed in BUILD mode
- Permission model (which users can call which tools)
Stage 3c: Self-sufficiency
- Per-agent isolated databases
- Credential vault per agent
- DNA export/import (fork an organism)
Try It Live
bash
npm start
# Then open http://localhost:3210/talk
# Try this sequence:
# 1. "List all agents and available skills"
# 2. "Create an agent called contact-manager that manages contacts,
# with skills add_contact, query_org, send_message"
# 3. "Add Merlin, phone 9447774135, role Assistant, language English"
# 4. "Who is in the org?"UX Enhancements (Stage 3a.1)
Thread Continuity
The /talk UI maintains conversation context across messages:
- Each browser session gets a persistent
threadId(stored in localStorage) - Messages are tagged with the threadId
- Server loads the last 10 messages of a thread and includes them in the agent prompt
- Axiom remembers what was discussed — can refer back, build on context
- "+ New chat" button generates a new threadId, clears the UI, fresh context
ChatGPT-Style UI
Clean, minimal chat interface:
- User messages on the right (blue bubble)
- Assistant messages on the left (no bubble, just avatar + markdown)
- Auto-resizing textarea, Enter to send, Shift+Enter for newline
- Debug info hidden by default — collapsible
detailsunder each reply - Expanded details show: trace ID, tokens, skills called, full X-Ray event stream
- Markdown rendering: bold, lists, code blocks, inline code
One-Agent-Per-Domain Rule (Axiom instruction)
Axiom now follows this principle when growing the organism:
- Same domain → extend the existing agent. Add a new skill to it.
- Different domain → new agent.
- When unsure → extend. Splitting later is easy; merging later is hard.
This prevents agent sprawl. An agent that "owns" attendance should handle marking it, querying it, and reporting on it — not get split into attendance-marker + attendance-reporter.