Zoid + SO1 Automations — Deployment Checklist
Speed-run guide. Do steps in order — each unlocks the next.Phase 0: External Services (~30 min)
These are pre-requisites. Do them first so IDs/URLs are ready when you need them.0A. Discord Webhooks
- Create
#council-decisionschannel - Channel Settings > Integrations > Webhooks > New Webhook
- Copy URL → save as
DISCORD_WEBHOOK_COUNCIL - Create
#agent-optimisationchannel, repeat - Copy URL → save as
DISCORD_WEBHOOK_OPTIM
0B. Airtable — Council Base
Go to airtable.com > Create base: “OpenClaw Council” Table 1: “Council Decisions”| Field | Type |
|---|---|
| Type | Single select: New Project, Priority Conflict, Crisis, Financial, Shipping |
| Verdict | Single select: GO, NO-GO, DEFER, RESOLVED |
| Confidence | Number (0.00–1.00) |
| Summary | Long text |
| Compass_Score | Number |
| Vault_Score | Number |
| Cortex_Score | Number |
| Anvil_Score | Number |
| Tempo_Score | Number |
| Date | Date |
| Session_ID | Single line text |
| 30_Day_Review | Checkbox |
| Review_Outcome | Long text |
| Field | Type |
|---|---|
| From_Agent | Single select: anvil, bard, vault, cortex, tempo, compass, sentinel, atlas |
| To_Agent | Single select (same 8) |
| Type | Single select: assessment, estimation, feasibility, approval, information |
| Question | Long text |
| Response | Long text |
| Quality_Score | Number |
| Date | Date |
| Field | Type |
|---|---|
| Date | Date |
| Signals_Active | Number |
| Triggered_Signals | Long text |
| Recovery_Duration_Days | Number |
| Post_Recovery_Outcome | Long text |
https://airtable.com/appXXXXXXXXX/...) → save as AIRTABLE_COUNCIL_BASE_ID.
0C. Airtable — Optimisation Base
Create base: “OpenClaw Optimisation” Table 1: “Optimisation Runs”| Field | Type |
|---|---|
| Agent | Single line text |
| Template | Single line text (e.g. U-01, G-01) |
| Run Date | Date |
| Score | Number (0.00–1.00) |
| Status | Single select: OK, WARNING, ACTION_REQUIRED, SKIPPED |
| Recommendations | Long text |
| Cost USD | Currency |
| Tokens Used | Number |
| Field | Type |
|---|---|
| Agent | Single line text |
| Dimension | Single select: tone, scope, protocol, consistency |
| Score | Number |
| Date | Date |
| Trend | Single select: improving, stable, worsening |
| Field | Type |
|---|---|
| Agent | Single line text |
| Protocol | Single select (8 protocols) |
| Week Of | Date |
| Activation Rate | Percent |
| Success Rate | Percent |
| Effectiveness | Percent |
| Status | Single select: effective, underused, ineffective, critical |
| Field | Type |
|---|---|
| Date | Date |
| Total Calls | Number |
| Total Cost USD | Currency |
| Skipped Runs | Number |
| Skip Reason | Single select: hourly_limit, daily_limit, cost_cap |
AIRTABLE_OPTIM_BASE_ID.
0D. Airtable API Token
airtable.com/create/tokens > Create personal access token with scopes:data.records:readdata.records:write- Access to both bases above
Phase 1: BFF → hab.so1.io Connectivity (~5 min)
1A. Get n8n API Key
- Go to
hab.so1.io - Settings (gear icon) > API
- Enable API if not already enabled
- Create new API key → copy it
1B. Set Railway Env Vars
In Railway dashboard for thecontrol.so1.io service, add:
1C. Verify
Phase 2: n8n Credentials & Variables (~10 min)
2A. Credentials (hab.so1.io > Settings > Credentials)
Create two credentials:-
anthropic-api— Type: “Header Auth”- Name:
x-api-key - Value: your Anthropic API key (
sk-ant-...)
- Name:
-
airtable-api— Type: “Header Auth”- Name:
Authorization - Value:
Bearer <airtable_pat_from_0D>
- Name:
2B. Variables (hab.so1.io > Settings > Variables)
Add all of these:Phase 3: Import Council Workflows (~15 min)
Source file:standalone/zoid/agents/COUNCIL-WORKFLOWS.md
3A. Import Workflow JSON
For each workflow (CW-01 through CW-07):- Go to
hab.so1.io> Workflows > + Add Workflow > Import from JSON - Copy the JSON block from
COUNCIL-WORKFLOWS.mdfor that workflow - Paste and import
- Verify tags — each workflow should already have tags in the JSON. Confirm they appear in the workflow settings. These tags are critical for the console to link agents to workflows.
| Workflow | Tags (must match exactly) |
|---|---|
| CW-01: New Project Evaluation | openclaw, council, cw-01, compass, vault, cortex, anvil, tempo, atlas |
| CW-02: Priority Conflict Resolution | openclaw, council, cw-02, atlas, compass |
| CW-03: Weekly Strategy Sync | openclaw, council, cw-03, atlas, compass, sentinel, strategy |
| CW-04: Financial Decision Gate | openclaw, council, cw-04, vault, compass, atlas, strategy |
| CW-05: Shipping Decision | openclaw, council, cw-05, anvil, sentinel, atlas, builder |
| CW-06: Content Calendar Planning | openclaw, council, cw-06, bard, cortex, atlas, voice |
| CW-07: ADHD Emergency Protocol | openclaw, council, cw-07, adhd, atlas, tempo, compass, bard, human |
- Do NOT activate yet — test first (Phase 5).
3B. Quick Smoke Test
Pick CW-01. Click “Test workflow” in the n8n editor. It should:- Hit the webhook trigger (or use manual trigger for testing)
- Fail at the LLM node if credential isn’t wired — that’s expected
- Wire the
anthropic-apicredential to each LLM node, then re-test
Phase 4: Import Optimisation Workflows (~20 min)
Source files:- Skeleton:
standalone/zoid/agents/OPTIM-N8N-SUITE.md(section 4.3) - Prompts:
standalone/zoid/agents/OPTIM-HANDBOOK.md
4A. Import Skeleton
- Import the skeleton JSON from OPTIM-N8N-SUITE.md section 4.3
- Save as
optim-skeleton(don’t activate)
4B. Create Template Workflows
For each of the 17 templates, duplicate the skeleton and customise: Start with these 3 (they have ready-made JSON in OPTIM-N8N-SUITE.md):| Template | Section | Cron |
|---|---|---|
| U-01: Prompt Drift | section “Template-Specific: U-01” | 0 2 * * 0 (Sun 02:00) |
| U-05: ADHD Protocol | section “Template-Specific: U-05” | 0 3 * * 0 (Sun 03:00) |
| G-01: Shipping Velocity | section “Template-Specific: G-01” | 0 18 * * 5 (Fri 18:00) |
- Duplicate
optim-skeleton - Rename to
optim-u01-prompt-drift(etc.) - Replace the “Build Analysis Prompt” node with the template-specific version from OPTIM-N8N-SUITE.md
- Update the Schedule Trigger cron
- Update Agent Iterator filter (if group/individual template)
- Tag with
optim+ agent-specific tags
| ID | Name | Cron | Agents |
|---|---|---|---|
| U-02 | Memory Hygiene | 0 2 * * * (daily) | all |
| U-03 | Voice Consistency | 0 4 1,15 * * (fortnightly) | all |
| U-04 | Context Budget | 0 5 1 * * (monthly) | all |
| U-06 | Council Handoff | 0 4 * * 0 (Sun) | all (runs once) |
| U-07 | Tool Relevance | 0 5 15 * * (monthly) | all |
| U-08 | Regression Testing | 0 6 1 * * (monthly) | all |
| U-09 | Personality Entropy | 0 7 1 * * (monthly) | all |
| U-10 | Config Drift | 0 5 1 1,4,7,10 * (quarterly) | all |
| G-02 | Decision Quality | 0 18 * * 5 (Fri) | compass, atlas, vault |
| G-03 | Growth & Wellbeing | 0 4 30 * * 0 (Sun) | tempo, cortex |
| G-04 | Content Quality | event-driven | bard, cortex |
| I-01 | Debt/Shipping Ratio | 0 5 1,15 * * (fortnightly) | anvil |
| I-02 | Authenticity | 0 6 30 * * 1 (Mon) | bard |
| I-03 | Priority Accuracy | 0 6 * * 1 (Mon) | atlas |
4C. Wire Credentials
For every imported workflow, ensure:- LLM nodes use the
anthropic-apicredential - Airtable HTTP nodes use the
airtable-apicredential
Phase 5: Import Life Hacks (~10 min)
Source:automation-workflows/life-hacks/workflows/
Each has a JSON file ready to import:
| Workflow | JSON File | Extra Credentials Needed |
|---|---|---|
| Daily Compass | daily-compass/daily-compass.json | Google OAuth2, GitHub PAT, Starling API, OpenWeatherMap |
| Inbox Pilot | inbox-pilot/inbox-zero-autopilot.json | Google OAuth2, Anthropic |
| Money Pilot | money-pilot/money-pilot.json | Starling API, Anthropic |
| Health Pulse | health-pulse/health-pulse.json | Apple Health (via webhook), Anthropic |
| Decision Journal | decision-journal/decision-journal.json | Airtable, Anthropic |
swim-coach-weekly-scheduler.jsonswim-coach-session-briefs.jsonswim-coach-log-webhook.jsonswim-coach-adaptation.jsonswim-coach-afternoon-swimdown.json
SETUP.md with specific credential requirements. Read those for per-workflow setup.
Tip: Start with Daily Compass only — it’s the most useful day-one. Add others later.
Phase 6: Verify End-to-End (~10 min)
6A. Console Shows Workflows
- Visit
console.so1.io/workflows - Should list all imported workflows with active/inactive status
- If empty: check Railway logs for BFF → n8n connection errors
6B. Console Shows Agent → Workflow Links
- Visit
console.so1.io/agents - Each agent card should show a workflow count
- Click into an agent (e.g. Anvil) → “Linked Workflows” section should list CW-01, CW-05, G-01, etc.
- If counts are 0: verify workflow tags in n8n match agent
workflowTagsin config
6C. Console Shows Runbooks
- Click into any agent with runbooks (e.g. Sentinel)
- “Runbooks” section should show entries like “Automation Operations”, “DevOps Operations”
6D. Test Workflow Execution
- In the console, click into an agent with a linked workflow
- Click “Run” on one of the workflows
- Check
console.so1.io/jobs— should show a running/completed execution - Check Discord channels for notifications
6E. Smoke Test Council Workflow
Activation Order
Once everything tests clean, activate workflows in this order:- Council workflows (CW-01 through CW-07) — these are webhook-triggered, so activating just enables the endpoints
- U-02 Memory Hygiene — daily, low cost, validates the skeleton pattern works
- U-01 Prompt Drift — weekly, core health metric
- Daily Compass — morning briefing, immediate personal value
- Remaining optimisation workflows — one per day, monitoring cost in Rate Limiter Log
- Life hacks — as you set up the per-workflow credentials
Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
| Console workflows page shows error | N8N_API_URL / N8N_API_KEY not set on Railway | Set env vars, redeploy |
| Agent workflow count is 0 | Workflow tags in n8n don’t match workflowTags in agent config | Check tag names are lowercase and match exactly |
| LLM node fails in n8n | anthropic-api credential not wired to node | Edit workflow, select credential on each LLM node |
| Airtable logging fails | Wrong base ID or PAT scope | Verify AIRTABLE_*_BASE_ID variables, check PAT has both bases in scope |
| Discord notification missing | Webhook URL wrong or channel deleted | Test webhook URL with curl directly |
| Rate limiter blocks all runs | Daily cost cap hit | Check “Rate Limiter Log” table; increase OPTIM_DAILY_COST_CAP if needed |
| Console shows “no runbooks” | Agent runbooks array empty in config | Check config/agents.ts — vault and tempo intentionally have none yet |