Summary
Each chat bridge installer (bridges/kimaki.sh, bridges/cc-connect.sh, bridges/telegram.sh) writes a CLI-channel config entry consumed by DMC's generic CLI transport runtime (separate issue: Extra-Chill/data-machine-code#412). The runtime is generic; the per-bridge config makes each transport addressable via agents/dispatch-message.
This issue also tracks retirement of the legacy /opt/agent-ping-webhook/ stack that currently fills this role on the Extra Chill VPS (and any other install using it).
Background
Today on the Extra Chill VPS, outbound dispatch to kimaki goes through:
```
data-machine flow "EC Agent Progress Ping" (every 3 days)
└─ datamachine/agent-call ability
└─ POST https://extrachill.com/agent-ping/
└─ nginx proxy → 127.0.0.1:8422
└─ /opt/agent-ping-webhook/webhook.py (Python BaseHTTPServer, systemd unit)
└─ subprocess.Popen(['kimaki','send','--channel',...,'--prompt',...])
```
The Python webhook is currently broken — it reads payload.get('prompt') but the modern agent-call payload uses task, so every dispatch returns `400 No message content`. Beyond the bug, the whole stack is architecturally wrong:
- The Python script lives outside any plugin or repo, undeployable via homeboy.
- It only handles kimaki (despite three bridges existing in this repo).
- Authentication, payload shape, and process lifecycle are all hand-rolled.
- The receiving end of an outbound dispatch should be a configured channel runtime, not an orphan service.
Proposed change
Per-bridge config write
When a bridge installs (or upgrades), it writes a channel config entry that DMC's CLI runtime consumes. Two reasonable mechanisms — pick one per the broader infrastructure model:
Option A: mu-plugin file (preferred — file-based, version-controlled-ish, no DB write)
```
$WP_PATH/wp-content/mu-plugins/wp-coding-agents-channels.php
```
Each bridge appends/replaces its block. File registers entries via the `datamachine_code_cli_channels` filter.
Option B: WP option (simpler, DB-stored)
```
wp option update datamachine_code_cli_channels '{ "kimaki": {...}, "cc-connect": {...} }' --format=json
```
Example bridge config: kimaki
```php
'kimaki' => [
'command' => '/usr/local/bin/kimaki', // resolved at install time
'args' => [ 'send', '--channel', '{recipient}', '--prompt', '{message}' ],
'detach' => true,
'timeout' => 600,
],
```
Then a data-machine flow step calls:
```
agents/dispatch-message
channel: 'kimaki'
recipient: '1476075959806590989' // discord channel id (replaces webhook URL)
message: 'Time for your check-in.'
```
…and DMC's CLI runtime shells the configured command. No HTTP, no Python, no nginx hop.
Bridges in scope
bridges/kimaki.sh — `channel='kimaki'`
bridges/cc-connect.sh — `channel='cc-connect'`
bridges/telegram.sh — `channel='telegram'` (this one's a 2-service bridge; map carefully — the user-facing entry is presumably `opencode-telegram`)
Each bridge's existing install hook (`bridge_install` / `__install_systemd`) is the right place for the config write.
Resolved command paths
The config's `command` should be the absolute path resolved at install time, not a PATH-dependent name. For systemd-installed bridges, this is typically:
- VPS: `/usr/local/bin/datamachine-kimaki` (the shim already installed by `bridges/kimaki.sh`), or `/usr/local/bin/kimaki` from the global npm install.
- Local: `$HOME/.local/bin/datamachine-kimaki` or whatever `npm ls -g kimaki` resolves to.
Bridges already know how to resolve this — they install the shim binaries themselves.
Recipient semantics per bridge
Each bridge defines what `recipient` means for it:
- kimaki: Discord channel/guild ID (numeric string). Substituted into `--channel`.
- cc-connect: TBD — depends on bridge's CLI surface; document in `bridges/cc-connect.sh`.
- telegram: chat ID or username, depending on bot config.
These belong in the bridge's own README/inline docs, not in DMC.
Legacy retirement
After Extra-Chill/data-machine-code#412 + this change deploys:
- Reconfigure the EC Agent Progress Ping flow to use `agents/dispatch-message` (`channel=kimaki, recipient=1476075959806590989`) instead of `agent-call` posting to `https://extrachill.com/agent-ping/\`.
- Verify the flow runs successfully (manual run via `wp datamachine flow run 4`).
- Disable + remove the legacy service:
- `systemctl disable --now agent-ping-webhook.service`
- `rm /etc/systemd/system/agent-ping-webhook.service`
- `rm -rf /opt/agent-ping-webhook/`
- Remove the `location /agent-ping/` block from `/etc/nginx/sites-available/extrachill` and reload nginx.
- Free port 8422.
- Remove `/home/opencode/.secrets/agent-ping-token.txt` (no longer used).
Any other install of wp-coding-agents that ran the old setup with the Python webhook should follow the same retirement path. Worth checking if an `uninstall-legacy-agent-ping.sh` helper script makes sense to include in this repo.
Acceptance criteria
Related
Out of scope
Summary
Each chat bridge installer (
bridges/kimaki.sh,bridges/cc-connect.sh,bridges/telegram.sh) writes a CLI-channel config entry consumed by DMC's generic CLI transport runtime (separate issue: Extra-Chill/data-machine-code#412). The runtime is generic; the per-bridge config makes each transport addressable viaagents/dispatch-message.This issue also tracks retirement of the legacy
/opt/agent-ping-webhook/stack that currently fills this role on the Extra Chill VPS (and any other install using it).Background
Today on the Extra Chill VPS, outbound dispatch to kimaki goes through:
```
data-machine flow "EC Agent Progress Ping" (every 3 days)
└─ datamachine/agent-call ability
└─ POST https://extrachill.com/agent-ping/
└─ nginx proxy → 127.0.0.1:8422
└─ /opt/agent-ping-webhook/webhook.py (Python BaseHTTPServer, systemd unit)
└─ subprocess.Popen(['kimaki','send','--channel',...,'--prompt',...])
```
The Python webhook is currently broken — it reads
payload.get('prompt')but the modernagent-callpayload usestask, so every dispatch returns `400 No message content`. Beyond the bug, the whole stack is architecturally wrong:Proposed change
Per-bridge config write
When a bridge installs (or upgrades), it writes a channel config entry that DMC's CLI runtime consumes. Two reasonable mechanisms — pick one per the broader infrastructure model:
Option A: mu-plugin file (preferred — file-based, version-controlled-ish, no DB write)
```
$WP_PATH/wp-content/mu-plugins/wp-coding-agents-channels.php
```
Each bridge appends/replaces its block. File registers entries via the `datamachine_code_cli_channels` filter.
Option B: WP option (simpler, DB-stored)
```
wp option update datamachine_code_cli_channels '{ "kimaki": {...}, "cc-connect": {...} }' --format=json
```
Example bridge config: kimaki
```php
'kimaki' => [
'command' => '/usr/local/bin/kimaki', // resolved at install time
'args' => [ 'send', '--channel', '{recipient}', '--prompt', '{message}' ],
'detach' => true,
'timeout' => 600,
],
```
Then a data-machine flow step calls:
```
agents/dispatch-message
channel: 'kimaki'
recipient: '1476075959806590989' // discord channel id (replaces webhook URL)
message: 'Time for your check-in.'
```
…and DMC's CLI runtime shells the configured command. No HTTP, no Python, no nginx hop.
Bridges in scope
bridges/kimaki.sh— `channel='kimaki'`bridges/cc-connect.sh— `channel='cc-connect'`bridges/telegram.sh— `channel='telegram'` (this one's a 2-service bridge; map carefully — the user-facing entry is presumably `opencode-telegram`)Each bridge's existing install hook (`bridge_install` / `__install_systemd`) is the right place for the config write.
Resolved command paths
The config's `command` should be the absolute path resolved at install time, not a PATH-dependent name. For systemd-installed bridges, this is typically:
Bridges already know how to resolve this — they install the shim binaries themselves.
Recipient semantics per bridge
Each bridge defines what `recipient` means for it:
These belong in the bridge's own README/inline docs, not in DMC.
Legacy retirement
After Extra-Chill/data-machine-code#412 + this change deploys:
Any other install of wp-coding-agents that ran the old setup with the Python webhook should follow the same retirement path. Worth checking if an `uninstall-legacy-agent-ping.sh` helper script makes sense to include in this repo.
Acceptance criteria
/opt/agent-ping-webhook/retirement steps are documented (and ideally automated).Related
Out of scope