cambium ▸ docs/OBADIAH_V2_PLAN.md
updated 2026-03-28

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)

  1. Claude starts fresh — no persistent state
  2. Reads SOUL.md (personality), USER.md (Joshua’s profile), CLAUDE.md (operating instructions)
  3. Reads today’s + yesterday’s daily memory from memory/daily/
  4. Checks changelog/CHANGELOG.md for recent self-improvements
  5. If heartbeat: executes heartbeat.md checklist

Persona Routing

Memory

Approval Gates

Discord Integration

What’s Missing


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:

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_detectedgovernance.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)

5.2 Discord Plugin

5.3 GitHub

5.4 Calendar / Scheduling

5.5 PAM


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

What gets better

What’s new


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

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:

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

  1. 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?

  2. 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?

  3. 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?

  4. 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).

  5. 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.

  6. 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.

  7. 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?

  8. 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.

  9. Cambium readiness. The Cambium docs describe a V1 architecture, but the reality-check/01-current-state.md may reveal gaps between design and implementation. What’s actually built today vs what needs building before Obadiah can migrate?

  10. 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.