Obadiah V2 on Cambium — Migration Plan
1. Vision
Obadiah V2 is the same Chief of Staff — same personality, same team, same protocols — but running as a living organism on Cambium instead of a collection of markdown files interpreted by a fresh Claude session each time. Personas become real agents with lifecycle and memory. Routines become graph-based workflows with durable state, checkpoints, and governance. The result: Obadiah that remembers, adapts, recovers from failures, and operates continuously without relying on a human to boot-sequence him every session.
2. Current State — How Obadiah Works Today
Boot Sequence (Every Session)
- Claude starts fresh — no persistent state
- Reads
SOUL.md(personality),USER.md(Joshua’s profile),CLAUDE.md(operating instructions) - Reads today’s + yesterday’s daily memory from
memory/daily/ - Checks
changelog/CHANGELOG.mdfor recent self-improvements - If heartbeat: executes
heartbeat.mdchecklist
Persona Routing
- 8 specialist personas (Arnold, MacKenzie, Tesla, Branson, Mr. T, Cipher, Vega, Shade) defined as markdown files in
personas/ - Obadiah routes by: explicit request, domain match, or multi-persona synthesis
- Delegation is either inline (load persona file, respond in voice) or subagent (spawn Claude with persona context)
Memory
- Daily logs written to
memory/daily/YYYY-MM-DD.md - Long-term knowledge in
memory/long-term/ - Memory is just files — no indexing, no search, no event history
Approval Gates
- External comms (email, social, public) require explicit YES
- Spending money requires explicit YES
- Everything else: execute, then report
Discord Integration
- Emoji-first acknowledgment (react within 5 seconds)
- Morning brief to #general at 6am Berlin
- Evening wrap to #general at 9pm Berlin
- Security alerts to #secure-it
- Multi-part message protocol (
...= wait,.= proceed)
What’s Missing
- No persistence between sessions — Obadiah wakes up with amnesia every time
- No durable task tracking — tasks exist only in conversation context
- No health monitoring — if a task fails, nobody knows unless Joshua checks
- No recovery — interrupted work is lost
- No concurrent operation — one Claude session at a time
- No audit trail — decisions aren’t logged in a queryable system
- Personas are static — no learning, no performance tracking, no lifecycle
3. Target Architecture — Obadiah on Cambium
3.1 Personas as Cambium Agents
Each persona becomes a Cambium agent template in Genesis.
| Persona | Template Name | Agent Type | Capabilities |
|---|---|---|---|
| Obadiah (self) | obadiah_chief_of_staff |
llm_reasoner |
delegation, synthesis, task_management, communication |
| Arnold | arnold_health_fitness |
llm_reasoner |
health_analysis, fitness_planning, nutrition |
| MacKenzie | mackenzie_finance |
llm_reasoner |
financial_analysis, tax_planning, budgeting |
| Tesla | tesla_innovation |
llm_reasoner |
ideation, technical_design, brainstorming |
| Branson | branson_entrepreneurship |
llm_reasoner |
business_strategy, startup_validation, market_analysis |
| Mr. T | mrt_security |
llm_reasoner |
security_audit, credential_management, threat_assessment |
| Cipher | cipher_qa |
llm_reasoner |
testing, bug_analysis, code_review |
| Vega | vega_marketing |
llm_reasoner |
marketing_strategy, aso, growth_analysis |
| Shade | shade_ux |
llm_reasoner |
ux_design, user_research, design_critique |
Lifecycle behavior: - Personas are instantiated on-demand when Obadiah routes work to them (Genesis) - They hibernate between tasks (state preserved, no resource burn) - They are composted after extended inactivity, with learnings fed back into template improvements - Trust scores track which personas deliver well on which task types
Agent config includes:
- system_prompt: contents of the persona’s markdown file
- tools: Claude API, relevant project access, Discord (for direct channel posting)
- resource_budget: token limits per task, max execution time
- policies: approval gates bound at the agent level
3.2 Routines as Hypha Workflows
| Current Routine | Cambium Workflow | Trigger |
|---|---|---|
| Morning brief (6am Berlin) | obadiah.morning_brief |
Scheduled (cron-like) |
| Evening wrap (9pm Berlin) | obadiah.evening_wrap |
Scheduled |
| Security audit | obadiah.security_audit |
Scheduled (daily) + on-demand |
| Task delegation | obadiah.task_delegation |
Signal: incoming message or explicit request |
| Proactive monitoring | obadiah.proactive_monitor |
Continuous (polling loop) |
| Self-improvement | obadiah.self_improvement |
Scheduled (weekly) + on-demand |
Each workflow is a Hypha graph with nodes, edges, retries, fallbacks, and checkpoints. See Section 4 for concrete definitions.
3.3 Approval Gates as Quorum Policies
// Quorum policy definitions for Obadiah
const obadiahPolicies = [
{
id: "external_comms",
name: "External Communications Gate",
description: "Any outbound email, social post, or public content",
type: "single_approver",
approver: "joshua",
timeout_ms: null, // no auto-approve — wait indefinitely
timeout_action: "block",
applies_to: ["send_email", "post_social", "publish_content"]
},
{
id: "spending",
name: "Financial Spending Gate",
description: "Any action that costs money",
type: "single_approver",
approver: "joshua",
timeout_ms: null,
timeout_action: "block",
applies_to: ["make_purchase", "subscribe_service", "pay_invoice"]
},
{
id: "file_deletion",
name: "Important File Deletion Gate",
description: "Deleting files marked as important",
type: "single_approver",
approver: "joshua",
timeout_ms: 3600000, // 1 hour
timeout_action: "block",
applies_to: ["delete_important_file"]
},
{
id: "security_config",
name: "Security Configuration Gate",
description: "Changes to security-sensitive systems",
type: "single_approver",
approver: "joshua",
timeout_ms: 1800000, // 30 min
timeout_action: "block",
applies_to: ["modify_security_config"],
on_trigger: "signal_discord_secure_it" // also post to #secure-it
}
];
Everything else (research, building, organizing, improving) executes without gates — Obadiah reports after the fact.
3.4 Discord and Telegram as Signal Endpoints
Discord and Telegram become external integration agents in Cambium:
- Inbound: Messages arrive as
coord.work_availablesignals with payload containing channel, user, message content - Outbound: Workflow nodes emit delivery tasks routed to a
discord_messengerortelegram_messengeragent - Reactions: The task protocol (react within 5 seconds) becomes a hardwired receptor: any inbound message signal triggers an immediate reaction before routing to Obadiah for processing
Discord message → signal: coord.work_available → Obadiah receptor →
1. Immediate: discord_react (within 5s)
2. Route: determine workflow (task delegation, direct response, etc.)
3. Execute workflow
4. Deliver: discord_reply with result
Channel mapping:
- #general (1467158393633378447) — morning briefs, evening wraps, general updates
- #secure-it (1469745195036836026) — security alerts, immune signals with severity > 0.5
3.5 Memory as Durable Event Store
Today’s memory system (markdown files) gets replaced by Cambium’s event backbone + a dedicated memory layer:
| Current | V2 |
|---|---|
memory/daily/YYYY-MM-DD.md |
Queryable daily summary generated from event store |
memory/long-term/ files |
Persistent knowledge records in Postgres with vector embeddings |
| Session context (lost on restart) | Durable workflow run state — survives interruptions |
changelog/CHANGELOG.md |
Audit trail of all lifecycle.* and self-improvement events |
How it works:
- Every significant action emits an event (Cambium’s event backbone)
- Daily summaries are auto-generated from events by the evening_wrap workflow
- Long-term memory is a Postgres table with metadata, searchable by Obadiah agents
- Composting records from persona agents feed back into routing heuristics
Boot sequence becomes irrelevant. Obadiah doesn’t boot — he’s always running. When a persona agent wakes from hibernation, it loads relevant context from the event store and memory layer, not from markdown files.
3.6 PAM Integration as Monitored Sub-System
PAM (prediction market signals) becomes an external agent registered with Cambium:
PAM agent (external, polling) → detects signal →
signal: coord.marker_placed (type: "pam.prediction_signal") →
Obadiah receptor binds →
Route to appropriate workflow:
- High urgency (> 0.8): immediate alert to Joshua via Discord
- Medium (0.5-0.8): include in next morning brief
- Low (< 0.5): log for weekly review
PAM’s trust score starts at 0.5 and adjusts based on signal accuracy over time. The immune layer monitors PAM for anomalous behavior (sudden flood of signals, contradictory predictions).
4. Workflow Definitions
4.1 Morning Brief Workflow
[Check Calendar] ──┐
[Check PAM] ──┼──→ [Merge Context] → [Generate Brief] → [Format] → [Deliver to Discord]
[Check Projects] ──┤ ↓
[Check Memory] ──┘ [success]
│
└─ (fallback on any source failure) → [Merge Context] (partial)
{
"name": "obadiah.morning_brief",
"description": "Daily 6am Berlin morning briefing for Joshua",
"version": 1,
"trigger": {
"type": "schedule",
"cron": "0 6 * * *",
"timezone": "Europe/Berlin"
},
"checkpoint_policy": {
"at_nodes": ["generate_brief"],
"position": "before_and_after"
},
"policy_bindings": {},
"graph": {
"nodes": [
{ "id": "check_calendar", "type": "task", "config": { "capability": "calendar_read", "retry": 2 } },
{ "id": "check_pam", "type": "task", "config": { "capability": "pam_query", "retry": 1 } },
{ "id": "check_projects", "type": "task", "config": { "capability": "project_status", "retry": 1 } },
{ "id": "check_memory", "type": "task", "config": { "capability": "memory_query", "retry": 1 } },
{ "id": "merge_context", "type": "task", "config": { "capability": "text_analysis", "join": "partial" } },
{ "id": "generate_brief", "type": "task", "config": { "capability": "summarization", "agent_template": "obadiah_chief_of_staff" } },
{ "id": "format_brief", "type": "task", "config": { "capability": "text_formatting" } },
{ "id": "deliver", "type": "task", "config": { "capability": "discord_post", "channel": "1467158393633378447" } },
{ "id": "success", "type": "terminal_success" },
{ "id": "failure", "type": "terminal_failure" }
],
"edges": [
{ "from": "check_calendar", "to": "merge_context", "type": "default" },
{ "from": "check_calendar", "to": "merge_context", "type": "fallback" },
{ "from": "check_pam", "to": "merge_context", "type": "default" },
{ "from": "check_pam", "to": "merge_context", "type": "fallback" },
{ "from": "check_projects", "to": "merge_context", "type": "default" },
{ "from": "check_projects", "to": "merge_context", "type": "fallback" },
{ "from": "check_memory", "to": "merge_context", "type": "default" },
{ "from": "check_memory", "to": "merge_context", "type": "fallback" },
{ "from": "merge_context", "to": "generate_brief", "type": "default" },
{ "from": "merge_context", "to": "failure", "type": "conditional", "condition": "all_sources_failed" },
{ "from": "generate_brief", "to": "format_brief", "type": "default" },
{ "from": "format_brief", "to": "deliver", "type": "default" },
{ "from": "deliver", "to": "success", "type": "default" }
]
}
}
Signal flow: lifecycle.run_started → gather agents genesis’d → sources queried in parallel → merge joins partial results → Obadiah agent generates brief → formatted → posted to Discord #general → lifecycle.run_completed → agents composted.
No approval gate. Morning briefs are internal — no Quorum policy needed.
4.2 Task Delegation Workflow
Triggered when Joshua sends a message that requires work.
[Parse Request] → [Route Decision] → [Single Persona?] ──→ [Spawn Agent] → [Execute] → [Deliver Result]
[Multi Persona?] ──→ [Spawn N Agents] → [Parallel Execute] → [Synthesize] → [Deliver Result]
[Direct Obadiah?] ──→ [Execute Directly] → [Deliver Result]
↓
[Approval Needed?] ──→ [Quorum Gate] → [Execute on Approval]
{
"name": "obadiah.task_delegation",
"description": "Route incoming task to appropriate persona(s) and execute",
"version": 1,
"trigger": {
"type": "signal",
"binds_to": ["coord.task_requested"]
},
"checkpoint_policy": {
"at_nodes": ["execute_task", "parallel_execute", "synthesize"],
"position": "before_and_after"
},
"graph": {
"nodes": [
{ "id": "parse_request", "type": "task", "config": { "capability": "text_analysis", "agent_template": "obadiah_chief_of_staff" } },
{ "id": "route_decision", "type": "condition", "config": { "evaluator": "persona_router", "outputs": ["single_persona", "multi_persona", "direct_obadiah"] } },
{ "id": "check_approval", "type": "condition", "config": { "evaluator": "approval_classifier", "outputs": ["needs_approval", "no_approval"] } },
{ "id": "approval_gate", "type": "approval", "config": { "policy": "dynamic", "note": "policy selected by approval_classifier output" } },
{ "id": "spawn_single", "type": "task", "config": { "capability": "agent_genesis", "note": "Genesis spawns the matched persona agent" } },
{ "id": "spawn_multi", "type": "task", "config": { "capability": "agent_genesis_batch" } },
{ "id": "execute_task", "type": "task", "config": { "capability": "dynamic", "note": "routed to spawned persona agent" } },
{ "id": "parallel_execute", "type": "task", "config": { "capability": "dynamic", "join": "all", "note": "all persona agents execute in parallel" } },
{ "id": "synthesize", "type": "task", "config": { "capability": "synthesis", "agent_template": "obadiah_chief_of_staff" } },
{ "id": "execute_direct", "type": "task", "config": { "capability": "dynamic", "agent_template": "obadiah_chief_of_staff" } },
{ "id": "deliver_result", "type": "task", "config": { "capability": "discord_reply" } },
{ "id": "success", "type": "terminal_success" },
{ "id": "failure", "type": "terminal_failure" }
],
"edges": [
{ "from": "parse_request", "to": "route_decision", "type": "default" },
{ "from": "route_decision", "to": "check_approval", "type": "conditional", "condition": "single_persona" },
{ "from": "route_decision", "to": "check_approval", "type": "conditional", "condition": "multi_persona" },
{ "from": "route_decision", "to": "execute_direct", "type": "conditional", "condition": "direct_obadiah" },
{ "from": "check_approval", "to": "approval_gate", "type": "conditional", "condition": "needs_approval" },
{ "from": "check_approval", "to": "spawn_single", "type": "conditional", "condition": "no_approval_single" },
{ "from": "check_approval", "to": "spawn_multi", "type": "conditional", "condition": "no_approval_multi" },
{ "from": "approval_gate", "to": "spawn_single", "type": "default" },
{ "from": "approval_gate", "to": "failure", "type": "conditional", "condition": "rejected" },
{ "from": "spawn_single", "to": "execute_task", "type": "default" },
{ "from": "spawn_multi", "to": "parallel_execute", "type": "default" },
{ "from": "execute_task", "to": "deliver_result", "type": "default" },
{ "from": "parallel_execute", "to": "synthesize", "type": "default" },
{ "from": "synthesize", "to": "deliver_result", "type": "default" },
{ "from": "execute_direct", "to": "deliver_result", "type": "default" },
{ "from": "deliver_result", "to": "success", "type": "default" }
]
}
}
Key behavior: The route decision node uses the same logic currently in CLAUDE.md — explicit persona request, domain match, or complexity assessment. The difference: it’s now a durable, inspectable decision with an audit trail.
4.3 Security Audit Workflow
[Scan Credentials] ──┐
[Scan .env Files] ──┼──→ [Merge Findings] → [Assess Severity] → [severity > 0.5?] ──→ [Alert #secure-it]
[Scan Git History] ──┤ [severity <= 0.5?] ──→ [Log Only]
[Check Access Logs]──┘
{
"name": "obadiah.security_audit",
"description": "Daily security scan across all projects",
"version": 1,
"trigger": {
"type": "schedule",
"cron": "0 3 * * *",
"timezone": "Europe/Berlin"
},
"checkpoint_policy": {
"at_nodes": ["assess_severity"],
"position": "after"
},
"graph": {
"nodes": [
{ "id": "scan_credentials", "type": "task", "config": { "capability": "security_scan", "agent_template": "mrt_security", "target": "credentials" } },
{ "id": "scan_env_files", "type": "task", "config": { "capability": "security_scan", "agent_template": "mrt_security", "target": "env_files" } },
{ "id": "scan_git_history", "type": "task", "config": { "capability": "security_scan", "agent_template": "mrt_security", "target": "git_secrets" } },
{ "id": "check_access_logs", "type": "task", "config": { "capability": "security_scan", "agent_template": "mrt_security", "target": "access_logs" } },
{ "id": "merge_findings", "type": "task", "config": { "capability": "text_analysis", "join": "partial" } },
{ "id": "assess_severity", "type": "condition", "config": { "evaluator": "severity_classifier", "outputs": ["high", "low"] } },
{ "id": "alert_discord", "type": "task", "config": { "capability": "discord_post", "channel": "1469745195036836026" } },
{ "id": "log_only", "type": "task", "config": { "capability": "event_log" } },
{ "id": "success", "type": "terminal_success" }
],
"edges": [
{ "from": "scan_credentials", "to": "merge_findings", "type": "default" },
{ "from": "scan_credentials", "to": "merge_findings", "type": "fallback" },
{ "from": "scan_env_files", "to": "merge_findings", "type": "default" },
{ "from": "scan_env_files", "to": "merge_findings", "type": "fallback" },
{ "from": "scan_git_history", "to": "merge_findings", "type": "default" },
{ "from": "scan_git_history", "to": "merge_findings", "type": "fallback" },
{ "from": "check_access_logs", "to": "merge_findings", "type": "default" },
{ "from": "check_access_logs", "to": "merge_findings", "type": "fallback" },
{ "from": "merge_findings", "to": "assess_severity", "type": "default" },
{ "from": "assess_severity", "to": "alert_discord", "type": "conditional", "condition": "high" },
{ "from": "assess_severity", "to": "log_only", "type": "conditional", "condition": "low" },
{ "from": "alert_discord", "to": "success", "type": "default" },
{ "from": "log_only", "to": "success", "type": "default" }
]
}
}
Immune integration: If the security audit detects a critical finding (leaked API key, unauthorized access), it emits immune.anomaly_detected with severity > 0.8, which triggers the hardwired cascade: immune.anomaly_detected → governance.escalation_required → immediate Quorum gate requiring Joshua’s acknowledgment.
4.4 Proactive Monitoring Workflow
A continuous workflow that monitors PAM signals, project health, and external events.
[Poll PAM] ──────────────→ [Evaluate Signal] → [High Priority?] → [Alert Joshua]
[Poll GitHub Activity] ──→ [Evaluate Signal] → [Medium?] ───────→ [Queue for Brief]
[Poll Project Health] ───→ [Evaluate Signal] → [Low?] ──────────→ [Log for Weekly]
↑ │
└────────────────── [Wait Interval] ←────────────────────────────────┘
{
"name": "obadiah.proactive_monitor",
"description": "Continuous monitoring of PAM, projects, and external signals",
"version": 1,
"trigger": {
"type": "continuous",
"interval_ms": 900000,
"note": "Every 15 minutes during business hours (8am-9pm Berlin)"
},
"graph": {
"nodes": [
{ "id": "poll_pam", "type": "task", "config": { "capability": "pam_query", "retry": 1 } },
{ "id": "poll_github", "type": "task", "config": { "capability": "github_activity", "retry": 1 } },
{ "id": "poll_projects", "type": "task", "config": { "capability": "project_health_check", "retry": 1 } },
{ "id": "evaluate", "type": "task", "config": { "capability": "signal_evaluation", "join": "partial", "agent_template": "obadiah_chief_of_staff" } },
{ "id": "priority_route", "type": "condition", "config": { "outputs": ["high", "medium", "low", "none"] } },
{ "id": "alert_joshua", "type": "task", "config": { "capability": "discord_dm" } },
{ "id": "queue_for_brief", "type": "task", "config": { "capability": "memory_write", "target": "morning_brief_queue" } },
{ "id": "log_weekly", "type": "task", "config": { "capability": "event_log" } },
{ "id": "wait_interval", "type": "wait", "config": { "duration_ms": 900000 } },
{ "id": "loop", "type": "task", "config": { "note": "re-triggers workflow" } }
],
"edges": [
{ "from": "poll_pam", "to": "evaluate", "type": "default" },
{ "from": "poll_pam", "to": "evaluate", "type": "fallback" },
{ "from": "poll_github", "to": "evaluate", "type": "default" },
{ "from": "poll_github", "to": "evaluate", "type": "fallback" },
{ "from": "poll_projects", "to": "evaluate", "type": "default" },
{ "from": "poll_projects", "to": "evaluate", "type": "fallback" },
{ "from": "evaluate", "to": "priority_route", "type": "default" },
{ "from": "priority_route", "to": "alert_joshua", "type": "conditional", "condition": "high" },
{ "from": "priority_route", "to": "queue_for_brief", "type": "conditional", "condition": "medium" },
{ "from": "priority_route", "to": "log_weekly", "type": "conditional", "condition": "low" },
{ "from": "priority_route", "to": "wait_interval", "type": "conditional", "condition": "none" },
{ "from": "alert_joshua", "to": "wait_interval", "type": "default" },
{ "from": "queue_for_brief", "to": "wait_interval", "type": "default" },
{ "from": "log_weekly", "to": "wait_interval", "type": "default" },
{ "from": "wait_interval", "to": "loop", "type": "default" }
]
}
}
Stigmergic behavior: When PAM signals consistently come from certain markets, the monitoring workflow places quality.high markers on those signal sources. Future runs weight those sources more heavily. When a source produces garbage, quality.low markers cause natural de-prioritization without anyone writing a rule.
5. Integration Points
5.1 Claude API (LLM Provider)
- Role: Primary LLM backend for all
llm_reasoneragents - Integration type: Cambium integration agent (
claude_provider) - Model: Claude Opus 4 (or current best) for Obadiah core and complex persona work; Sonnet for routine tasks (formatting, simple queries)
- Health monitoring: Latency and error tracking per-model; automatic fallback to Sonnet if Opus is degraded
- Budget: Token limits per agent per task, tracked by Health layer
5.2 Discord Plugin
- Role: Primary messaging surface
- Integration type: External agent with bidirectional signaling
- Inbound: Message events →
coord.task_requestedsignals - Outbound: Delivery tasks → Discord API (reply, react, edit_message)
- Channels: Mapped by ID in workflow configs
- Latency requirement: Reaction within 5 seconds (hardwired receptor, not workflow-dependent)
5.3 GitHub
- Role: Project monitoring, code review, PR tracking
- Integration type: API caller agent (
github_monitor) - Capabilities:
github_activity(poll for new PRs, issues, commits),github_project_health(check CI status, open issue count) - Projects monitored: Cambium, PAM, Family Dashboard, Whealthy, Unicorn.Land
5.4 Calendar / Scheduling
- Role: Time-aware context for morning briefs, meeting prep
- Integration type: API caller agent (
calendar_reader) - Capabilities:
calendar_read(today’s events),calendar_upcoming(next 7 days) - Note: Read-only integration. Obadiah never modifies calendar without approval gate.
5.5 PAM
- Role: Prediction market signal source
- Integration type: External agent (Python process registered with Cambium)
- Protocol: PAM polls markets → writes signals to shared Postgres table → Cambium’s
pam_monitoragent reads and emitscoord.marker_placedsignals - Trust: Starts at 0.5, adjusted by immune layer based on signal accuracy
6. Migration Path
Phase 1: Foundation (Week 1-2)
Goal: Cambium Core + Postgres running, one workflow executing end-to-end.
Tasks:
1. Deploy Cambium Core locally (Docker Compose: Postgres + modular monolith)
2. Run database migrations (pnpm --filter @cambium/db migrate)
3. Implement the morning_brief workflow as the first Hypha graph
4. Create the obadiah_chief_of_staff agent template in Genesis
5. Wire Discord integration as an external signal endpoint (inbound messages → signals, outbound → Discord API)
6. Execute one morning brief manually (trigger from Loom or CLI)
7. Verify: durable run state, event trail, checkpoint at generate_brief node
Success criteria: - Morning brief workflow runs end-to-end - Run is inspectable in Loom (or via API if Loom isn’t ready) - Events are persisted in Postgres - Seed checkpoint exists and could theoretically be replayed
What Joshua sees: Nothing changes yet. Obadiah V1 continues operating normally. Phase 1 runs in parallel as validation.
Phase 2: Scheduled Workflows (Week 3-4)
Goal: Morning brief + evening wrap + security audit running on schedule.
Tasks:
1. Implement scheduled triggers (cron-based workflow start)
2. Deploy obadiah.morning_brief on the 6am Berlin schedule
3. Build obadiah.evening_wrap workflow (similar structure to morning brief but pulls from day’s events)
4. Build obadiah.security_audit workflow with Mr. T agent template
5. Wire Discord delivery (post to #general and #secure-it)
6. Implement Quorum policy for security escalations
7. Verify: all three workflows run on schedule, deliver to Discord, handle source failures gracefully
Success criteria: - Joshua receives morning brief from Cambium (not V1 Obadiah) - Security audit runs daily, alerts appear in #secure-it when warranted - Failed source fetches use fallback edges, workflow still completes - Seed checkpoints exist for all runs
What Joshua sees: Morning briefs and security alerts start arriving more reliably. If a source is down, the brief still arrives (partial data). He can ask “what happened with this morning’s brief?” and get an answer from the event trail.
Phase 3: Persona Agents + Task Delegation (Week 5-8)
Goal: All 8 personas as Genesis templates. Task delegation workflow routing requests to the right persona.
Tasks:
1. Create agent templates for all 8 personas (system prompts from persona markdown files)
2. Implement obadiah.task_delegation workflow with routing logic
3. Implement persona hibernation (state preserved between tasks)
4. Wire inbound Discord messages to coord.task_requested signals
5. Implement multi-persona parallel execution and synthesis
6. Implement approval gates (Quorum) for external comms and spending
7. Build composting: after task completion, extract persona performance data
8. Migrate the 5-second reaction protocol to a hardwired receptor
Success criteria: - Joshua messages Discord, gets routed to the right persona - Multi-persona requests spawn parallel agents, Obadiah synthesizes - Approval gates block external comms until Joshua approves - Persona performance is tracked (which personas succeed at which tasks) - Composting records exist
What Joshua sees: Conversation feels the same — maybe better, because persona routing is more consistent and Obadiah can actually track what each persona did. He can ask “how did MacKenzie’s financial analysis go last week?” and get an answer.
Phase 4: Full Obadiah V2 + Loom Dashboard (Week 9-12)
Goal: Complete migration. V1 Obadiah retired. Loom provides operational visibility.
Tasks:
1. Deploy obadiah.proactive_monitor as continuous workflow
2. Integrate PAM as external agent with signal cascading
3. Build memory layer: daily summaries auto-generated from events, long-term knowledge in Postgres
4. Implement self-improvement workflow (weekly review of composting data, template optimization)
5. Wire Loom dashboard for Joshua: active workflows, pending approvals, persona health, recent events
6. Migrate all remaining V1 behavior to V2 workflows
7. Run V1 and V2 in parallel for 1 week (V2 as primary, V1 as fallback)
8. Retire V1
Success criteria: - Obadiah runs continuously without session boot - All workflows execute on schedule and on-demand - Memory persists across sessions (no more amnesia) - Loom shows Joshua what Obadiah is doing at any moment - PAM signals cascade through the system appropriately - Self-improvement creates measurable template optimizations - V1 can be shut down without loss of capability
What Joshua sees: Obadiah feels alive. He doesn’t have to re-explain context. Tasks survive interruptions. He can open Loom and see every workflow, every decision, every persona’s track record. Morning briefs are richer because they pull from a real event history, not yesterday’s markdown file.
7. What Changes for Joshua
What stays the same
- Talk to Obadiah on Discord (or Telegram) the same way
- Same personas, same voices, same emoji signals
- Same approval gates — external comms and spending still need his YES
- Same personality — SOUL.md becomes the system prompt for the Obadiah agent template
What gets better
- No more amnesia. Obadiah remembers everything because events persist in Postgres, not in markdown files that get read (or don’t) at boot
- Tasks survive interruptions. If Claude crashes mid-task, the Seed layer has a checkpoint. Work resumes, not restarts
- Parallel work. Multiple persona agents can work simultaneously on different tasks. No more “one Claude session at a time”
- Proactive monitoring. PAM signals, project health, and GitHub activity are continuously monitored — Joshua gets alerted when something matters, not when he remembers to ask
- Visibility. Loom dashboard shows what’s running, what’s blocked, what failed, and why. No more “hey Obadiah, what are you working on?”
- Self-improvement is tracked. Composting records show which personas improve over time, which templates work best, which workflows need tuning
- Reliability. Fallback paths, retries, and health monitoring mean the morning brief arrives even when a data source is down
What’s new
- Loom dashboard — optional, but there if he wants to see under the hood
- Approval queue — pending approvals visible in Loom (not just waiting in Discord DMs)
- Weekly report — auto-generated from composting data: what worked, what didn’t, what improved
8. AutoResearch Integration
8.1 What It Is
Autonomous experimentation loops inspired by Karpathy’s autoresearch. Obadiah can launch overnight experiment sessions that iterate on any measurable system — mutating parameters, evaluating results against a target metric, and converging on improvements without human supervision. By morning, Joshua wakes up to a summary of what was tried, what worked, and what Obadiah recommends.
8.2 How Obadiah Uses It
- PAM strategy optimization: Launch AutoResearch on
strategy.pyovernight. The experiment loop mutates trading parameters (thresholds, sleeves, edge requirements) and replays them against historical market data. Wake up to improved hit rates and confidence scores. - Content optimization: A/B test card content, email subject lines, social media posts. AutoResearch generates variants, scores them against engagement models or readability metrics, and surfaces winners.
- Self-improvement: Test prompt and persona variations against quality metrics. Obadiah literally improves its own responses — trying different system prompt phrasings, persona voice adjustments, or routing heuristics and measuring output quality.
- Portfolio monitoring: Experiment with different alert thresholds, scoring models for portfolio companies. Find the sensitivity settings that catch real problems without flooding Joshua with false positives.
8.3 Workflow Integration
AutoResearch sessions are Hypha workflows following the standard experiment loop pattern:
[Define Target Metric] → [Generate Mutations] → [Execute Experiment Batch] → [Score Results] →
[Converge?] ──yes──→ [Summarize Findings] → [Store Results] → [Done]
│ no
└──→ [Generate Mutations] (next generation)
Key integration points:
- Morning Brief enrichment: The
obadiah.morning_briefworkflow gains a new parallel source node —check_overnight_research— that pulls results from any AutoResearch sessions that completed overnight. If experiments ran, the morning brief includes a research summary section. - Problem-triggered launch: Obadiah can recommend launching an AutoResearch session based on observed problems. Example: if PAM’s hit rate drops below a threshold during proactive monitoring, Obadiah suggests an overnight optimization run.
- Quorum approval for production changes: Experiments that modify production systems or cost money require Quorum approval before execution. Read-only experiments against replay data run without gates.
- Results feed memory: All experiment results are logged as events in the durable event store, making them queryable by any workflow or persona agent.
8.4 Workflow Definition: AutoResearch Session
{
"name": "obadiah.autoresearch",
"description": "Autonomous experiment loop targeting a measurable metric",
"version": 1,
"trigger": {
"type": "signal",
"binds_to": ["coord.research_requested"]
},
"checkpoint_policy": {
"at_nodes": ["score_results", "summarize_findings"],
"position": "after"
},
"policy_bindings": {
"production_modification": "quorum:joshua_approval"
},
"graph": {
"nodes": [
{ "id": "define_target", "type": "task", "config": { "capability": "text_analysis", "agent_template": "obadiah_chief_of_staff", "note": "Parse target metric, baseline, and goal from request" } },
{ "id": "generate_mutations", "type": "task", "config": { "capability": "code_generation", "agent_template": "tesla_innovation", "note": "Generate parameter mutations for next batch" } },
{ "id": "execute_batch", "type": "task", "config": { "capability": "code_execution", "retry": 2, "note": "Run experiments against replay data or sandbox" } },
{ "id": "score_results", "type": "task", "config": { "capability": "data_analysis", "note": "Score each mutation against target metric" } },
{ "id": "check_convergence", "type": "condition", "config": { "evaluator": "convergence_checker", "outputs": ["converged", "continue", "budget_exhausted"] } },
{ "id": "summarize_findings", "type": "task", "config": { "capability": "summarization", "agent_template": "obadiah_chief_of_staff" } },
{ "id": "store_results", "type": "task", "config": { "capability": "memory_write", "target": "research_results" } },
{ "id": "success", "type": "terminal_success" },
{ "id": "failure", "type": "terminal_failure" }
],
"edges": [
{ "from": "define_target", "to": "generate_mutations", "type": "default" },
{ "from": "generate_mutations", "to": "execute_batch", "type": "default" },
{ "from": "execute_batch", "to": "score_results", "type": "default" },
{ "from": "execute_batch", "to": "failure", "type": "fallback" },
{ "from": "score_results", "to": "check_convergence", "type": "default" },
{ "from": "check_convergence", "to": "summarize_findings", "type": "conditional", "condition": "converged" },
{ "from": "check_convergence", "to": "generate_mutations", "type": "conditional", "condition": "continue" },
{ "from": "check_convergence", "to": "summarize_findings", "type": "conditional", "condition": "budget_exhausted" },
{ "from": "summarize_findings", "to": "store_results", "type": "default" },
{ "from": "store_results", "to": "success", "type": "default" }
]
}
}
8.5 Example: Overnight PAM Research
Obadiah receives: "Pam's hit rate is 40%, needs 55%"
Obadiah launches: AutoResearch session targeting strategy.py
Overnight: 100+ parameter mutations tested against replay data
Morning brief: "Pam research ran 127 experiments overnight.
Best result: hit_rate 52% (+12%), score 3.2 (+4.8).
Top modification: raised threshold_review_min_edge_bps to 150,
enabled contrarian sleeve with max_price 0.08.
Confidence gate: 4/6 passing (up from 1/6).
Recommendation: run 2 more overnight sessions to reach confidence."
8.6 Phase Mapping
Where AutoResearch fits in the migration phases:
| Phase | Timeline | AutoResearch Milestone |
|---|---|---|
| Phase 2 | Week 3-4 | Basic AutoResearch capability for PAM. Experiment loop runs against strategy.py with replay data. Results stored, surfaced in morning brief. |
| Phase 3 | Week 5-8 | AutoResearch available to all persona agents. Tesla can run innovation experiments, MacKenzie can optimize financial models, Vega can A/B test marketing content. |
| Phase 4 | Week 9-12 | Self-improvement loops for Obadiah’s own prompts. Persona system prompts, routing heuristics, and synthesis quality are all experimentable targets. Quorum gate on any self-modification that goes to production. |
8.7 Morning Brief Update
The obadiah.morning_brief workflow (Section 4.1) gains a new source node:
[Check Calendar] ──┐
[Check PAM] ──┤
[Check Projects] ──┼──→ [Merge Context] → [Generate Brief] → [Format] → [Deliver to Discord]
[Check Memory] ──┤
[Check Research] ──┘
The check_research node queries the event store for any obadiah.autoresearch workflow runs that completed since the last morning brief. If results exist, they are included in the merged context and appear as a dedicated “Overnight Research” section in the brief.
9. Open Questions
-
Scheduling infrastructure. Cambium V1 doesn’t mention cron-like triggers. Do we build a scheduler into Hypha, or use an external cron (systemd timer, cloud scheduler) that triggers workflows via API?
-
LLM context management. Persona agents need relevant context loaded from the memory layer. How much context? How do we select what’s relevant? Vector search over event history? RAG pipeline?
-
Discord plugin architecture. The current Discord plugin is a Claude Code plugin. For Cambium, do we build a new Discord integration agent, or wrap the existing plugin as an external agent?
-
Cost budget. Running 8 persona agents (even hibernating) plus continuous monitoring plus scheduled workflows will burn more tokens than a single Claude session. What’s the acceptable monthly cost? This affects agent resource budgets and model selection (Opus vs Sonnet per task).
-
Loom access for Joshua. Is Loom a web app he accesses via browser? A Discord bot that responds to inspection commands? Both? The UX for a single operator (Joshua) is very different from a team dashboard.
-
PAM integration depth. PAM is currently a Python project. Does it register as a Cambium external agent with its own heartbeat, or do we just poll its output database? The agent model gives us health monitoring and trust scoring. The polling model is simpler.
-
Telegram. The current setup supports Telegram alongside Discord. Should V2 treat Telegram as a second messaging surface with the same signal routing, or is Discord the primary and Telegram a fallback?
-
Self-modification scope. Today Obadiah can edit his own files (SOUL.md, protocols, etc.). In V2, can Obadiah modify his own workflow definitions? His own agent templates? This is powerful but needs governance — probably a Quorum gate on self-modification actions.
-
Cambium readiness. The Cambium docs describe a V1 architecture, but the
reality-check/01-current-state.mdmay reveal gaps between design and implementation. What’s actually built today vs what needs building before Obadiah can migrate? -
Rollback plan. If V2 has issues during migration, how quickly can we fall back to V1? The answer should be “instantly” — V1 is just markdown files and a Claude session. But we need to make sure V2 doesn’t modify V1’s files during the parallel-run period.