Design Questions: OpenClaw-OpenCode Bridge
Date: 2026-02-12
Status: Awaiting answers
Purpose: Clarify key architectural decisions before implementation
Context
We’re designing a multi-tier agent architecture:
DM Channel (WhatsApp/Slack)
↓
Personal Assistant (OpenClaw general purpose)
↓ (delegates workspace ops)
Orchestrator (OpenCode @ workspace-root)
↓ (reads/updates)
.ai/projectlist.md
↓ (creates/manages)
Builder Sessions (.builders/<project-id>-<name>/)
↓ (references detailed specs)
.ai/projects/<category>/<project-name>/
Key insight: Projects in projectlist.md ARE the sessions. Builder naming follows: .builders/<project-id>-<name>/
1. Orchestrator Workspace Structure
The orchestrator is a special OpenCode session that manages workspace-level operations.
Q1.1: Where should the orchestrator run?
Option A: Direct at workspace root (no builder workspace)
<workspace-root>/
├── .ai/
├── repos/
├── codev/
└── Taskfile.yaml
# Orchestrator runs here with `opencode acp --cwd .`
Option B: Dedicated orchestrator workspace
<workspace-root>/.orchestrator/
├── workspace-root/ (worktree → <workspace-root>)
# Orchestrator runs here
Your preference: A
Rationale: Don’t see any value in B
Q1.2: What should the orchestrator have access to?
Should it see:
- ✅
.ai/projectlist.md- Definitely needed - ✅
.ai/projects/- Needed to read project metadata - ✅
Taskfile.yaml- To run builder:init/cleanup tasks - ❓
repos/- All repos? Or only workspace-root? - ❓
.builders/- To inspect existing builders?
Your answer: Everything (in ~/src)
Q1.3: Should the orchestrator be always-running or on-demand?
Option A: Always-running daemon
- Starts with Gateway
- Personal Assistant sends requests via ACP
- Fast response (already running)
Option B: On-demand spawning
- Personal Assistant starts it when needed
- Terminates after completing operation
- Lower resource usage when idle
Your preference: A. We already run opencode web in a seperate pod (codev in the code-server ns) so i imagine we figure out how to get openclaw to communicate with that. It doesn’t start with the gateway, the server is expected to be running, and the orchestrator session is already there, so openclaw will probably just need to communicate with it.
2. Session-to-Project Mapping
Q2.1: How does projectlist.md map to .ai/projects/ locations?
Current examples from projectlist.md:
# Project 0012
files:
spec: .ai/projects/ai-dev/opencode-slack-integration/prd.md
# Project 0014
files:
plan: .ai/projects/tri-training/2026-02-12IMBuild/plan.mdShould we:
Option A: Add explicit metadata_path field
- id: "0014"
title: "Ironman Training"
metadata_path: .ai/projects/tri-training/2026-02-12IMBuild/
files:
plan: .ai/projects/tri-training/2026-02-12IMBuild/plan.mdOption B: Infer from spec/plan file path
- Parse directory from existing files.spec or files.plan
- Example:
files.spec=.ai/projects/ai-dev/foo/prd.md→ metadata at.ai/projects/ai-dev/foo/
Option C: Keep current approach (no automatic mapping)
- Orchestrator doesn’t need to know .ai/projects/ location
- User specifies repos when creating builder
Your preference: It’s implied by the files but we could use folders there instead of multiple files if easier?
Q2.2: How should the orchestrator discover which repos a project needs?
Option A: From .ai/projects/
{
"project_id": "0014",
"repos": ["ai-dev", "openclaw"],
"builder_name": "0014-ironman-training"
}Option B: From projectlist.md
- id: "0014"
title: "Ironman Training"
repos: [ai-dev] # Add new fieldOption C: User specifies when creating builder
User: "Create builder for project 0014, use repos ai-dev and openclaw"
→ Orchestrator creates builder with those repos
Option D: Combination
- metadata.json has defaults
- User can override when creating
Your preference: I think we probably maintain it in the projectlist - use whats in the project(s) as the default but allow more to be added?
3. Personal Assistant ↔ Orchestrator Communication
Q3.1: How does Personal Assistant invoke the Orchestrator?
Option A: Direct ACP calls (orchestrator always running)
Personal Assistant → HTTP POST to http://localhost:8080/sessions/orchestrator/messages
Body: { "content": "Create builder for project 0014 with repos ai-dev" }
Option B: Via OpenClaw tool wrapper
Personal Assistant → orchestrator tool (wraps ACP calls)
orchestrator(action='create_builder', project_id='0014', repos=['ai-dev'])
Your preference: I think this needs more research by you to make a recommendation, definitely prefer api calls to cli if possible
Q3.2: What operations should the orchestrator handle vs Personal Assistant?
Orchestrator handles:
- [✓ ] Create builder session
- [✓ ] Terminate builder session
- List all sessions (with git status per builder)
- Update projectlist.md status
- Link session to .ai/projects/ entry
- [✓ ] Sync builder workspace state back to repos
- [✓ ] Run Taskfile commands (builder:init, builder:cleanup)
Personal Assistant handles directly (no orchestrator):
- [✓ ] Show session status (query stored metadata)
- Route messages to existing builder sessions
- [✓ ] General conversation, questions, web searches
- Query projectlist.md (read-only)
- [✓ ] Non-workspace operations
Any others?
- [✓ ] Update projectlist.md status
4. Event Filtering and Chat Output
Q4.1: Which OpenCode events should be forwarded to chat?
Problem: Streaming all events (file_opened, file_changed, command_run, etc.) would be noisy and expensive.
Proposed filter (hardcoded, no AI processing):
Always forward:
-
agent.complete- “Done! Added rate limiting.” -
agent.question- “Should I write tests?” -
agent.error- “Build failed: missing dependency” -
agent.waiting_approval- “Need permission to run npm install”
Never forward:
-
agent.file_opened -
agent.file_read -
agent.thinking
Conditional (only if critical):
-
agent.command_run- Only if exit_code !== 0 -
agent.test_run- Only if tests failed
Your preferences:
Q4.2: Should we send a “started working” message?
User: "Add rate limiting"
OpenCode: "🔨 Working on it..." (immediate feedback)
[... silence while working ...]
OpenCode: "✅ Done! Added rate limiting." (completion)
Your answer: Sure
Q4.3: Where should session event history be stored?
For on-demand queries like “What did you change?”, we need full event history.
Option A: In-memory (Gateway)
- Fast, simple
- Lost on Gateway restart
- Suitable for short-lived sessions
Option B: Redis/Database
- Persistent across restarts
- Queryable, searchable
- More complex setup
Option C: File-based in builder workspace
.builders/0014-ironman-training/
├── workspace-root/
├── ai-dev/
└── .session-history.json # All events stored here
Option D: Don’t store (always query OpenCode session history API)
- Assumes ACP has session history endpoint
- No duplicate storage
- Depends on ACP capabilities
Your preference:
Q4.4: Should the orchestrator also use filtered events?
The orchestrator session itself will emit events when creating/managing builders.
Should orchestrator events be:
- Forwarded to DM channel (admin sees everything)?
- Logged only (silent background operations)?
- Filtered same as builder sessions?
Your answer: Should be the same as builders
5. Project Status Transitions
Q5.1: Should the orchestrator auto-update projectlist.md status?
Scenario: Personal Assistant asks orchestrator to create builder for project 0014.
Should orchestrator:
Option A: Auto-update status
Before: status: planned
Orchestrator creates builder
After: status: implementing
Option B: Manual only
- Orchestrator never modifies projectlist.md
- Human updates status explicitly
- Follows current workflow (human approval gates)
Option C: Suggest status change
Orchestrator: "Builder created. Suggest updating project 0014 status: planned → implementing. Approve?"
Personal Assistant relays to user via DM
User approves → orchestrator updates
Your preference: I think the update to projectlist happens first… So with human change to projectlist is agreed, then passed to orchestrator to reconcile
Q5.2: Which status transitions should require human approval?
From projectlist.md lifecycle:
conceived → specified → planned → implementing → implemented → committed → integrated
↑ ↑
Human approves Human approves
Current gates:
conceived→specified: Human must approve speccommitted→integrated: Human validates production
Should orchestrator be allowed to transition:
-
planned→implementing(when builder created) -
implementing→implemented(when PR created) -
implemented→committed(when PR merged)
Your answer: I think the personal assistant with human input does this.
-
planned→implementingpersonal assistant changes before handing to opencode -
implementing→implementedpersonal assistant changes when pr is raised by opencode -
implemented→committedpersonal assistant changes after merge & input from human
6. Multiple Builders Per Project
Q6.1: How to handle projects with multiple builders?
Example from projectlist.md:
- id: "0012"
notes: "Two builders: 0012-slack-gateway, 0012-bridge-plugin"Current structure:
.builders/
├── 0012-slack-gateway/
└── 0012-bridge-plugin/
Questions:
- How should user create multiple builders for one project?
- Should they share the same session_id (0012)?
- Or have separate IDs (0012a, 0012b)?
- How to track in projectlist.md?
Your answer: I think multiple builders for the same project, like the above, is fine. If there is more than one simultaneous builder in a category then a new group should be created for the subsequent one(s).
Q6.2: Should builders be linkable/aware of siblings?
If project 0012 has two builders, should they:
- Run independently (no awareness of each other)?
- Share context somehow (coordinated by orchestrator)?
- Have access to each other’s workspaces?
Your answer: Independent, before being spawned the integration rules should be agreed (e.g. an api contract)
7. Chat Binding Configuration
Q7.1: Where should chat bindings be stored?
Chat bindings link sessions to chat surfaces:
session_id: "0014"
platform: whatsapp
channel_id: "120363xxx@g.us"
trigger: all_messagesOption A: Gateway config file
# ~/.openclaw/config/bindings.yaml
bindings:
- session_id: "0014"
platform: whatsapp
channel_id: "120363xxx@g.us"Option B: In .builders/ workspace
.builders/0014-ironman-training/.binding.yaml
Option C: In projectlist.md
- id: "0014"
title: "Ironman Training"
chat_binding:
platform: whatsapp
channel_id: "120363xxx@g.us"Option D: Database/Redis
Your preference: I think we can store the info in projectlist (we might not need channel_id?) but ~/.openclaw needs to be correct
Q7.2: Should one project support multiple chat bindings?
Example: Project 0014 bound to BOTH:
- WhatsApp group (team collaboration)
- Slack thread (status updates)
Should this be allowed? Not in scope for now, but yaml should support multiple
If yes, how?
8. Builder Naming and Lifecycle
Q8.1: Confirm builder naming convention
Current pattern from projectlist.md:
.builders/<project-id>-<kebab-case-name>/
Examples:
.builders/0012-slack-gateway/.builders/0013-market-maker-mvp/.builders/0014-ironman-training/
Is this the standard we should follow? Yes
If no, what should it be?
Q8.2: When should builders be cleaned up?
Trigger options:
- When project status →
committed(PR merged) - When project status →
integrated(deployed) - When project status →
abandoned - [x ] Manual cleanup only (never automatic)
- After X days of inactivity
- When user explicitly requests termination
Your preferences: Manual for now, leave space in the spec to revisit automation later
Q8.3: Should cleanup preserve anything?
When cleaning up .builders/0014-ironman-training/:
Should we preserve:
- Session history/logs (move to
.ai/projects/.../session-history.json?) - Git commits (assume pushed to remote already)
- Local changes (fail cleanup if uncommitted changes?)
- Nothing (delete everything)
Your answer: Sounds good, needs to ensure there aren’t any uncommitted changes
9. Integration with Existing Projects
Q9.1: Backward compatibility with current .builders/
You mentioned:
Project 0013: "Built in .builders/0013-market-maker-mvp"
Project 0012: "Two builders: 0012-slack-gateway, 0012-bridge-plugin"
Are these builders:
- Already using the OpenCode session pattern?
- Created manually (not via orchestrator)?
- Something else?
Your answer: They are created manually, at the moment, but do loosely follow the pattern.
Q9.2: Migration path for existing projects
For projects already implementing with existing builders:
Should orchestrator:
- Detect and adopt existing builders?
- Require rebuild/recreation?
- Support both old and new patterns?
Your answer:
10. OpenCode ACP Discovery
Q10.1: Dependencies on Phase 0 discovery
Many design decisions depend on what OpenCode’s ACP actually supports.
Critical questions for Phase 0:
- Does ACP have a session history API?
- Can we specify event filtering mode when creating session?
- Does ACP support session metadata (tags, custom fields)?
- Can multiple clients attach to same session?
- Does ACP persist sessions across server restarts?
Should we:
- Answer architecture questions now (with assumptions)?
- Block on Phase 0 discovery first?
- Design generically to adapt later?
Your preference:
11. Additional Questions
Q11.1: Any other architectural concerns?
Q11.2: Priority order for implementation?
Once we have answers, what order should we implement?
Summary
Please annotate this document with your answers. Use HTML comments or add text directly.
When complete, this will form the foundation for:
- Updated
opencode-session-pattern.md(with orchestrator) - New
orchestrator-pattern.mddocument - Implementation specifications for the OpenClaw tool
- Gateway configuration schemas
Next Steps After This:
- You annotate with answers
- I review and create updated/new documentation
- We align on the architecture
- Phase 0: ACP protocol discovery (if not blocking)
- Implementation begins