Skip to content

fix: outbound delivery with JSON-RPC, channel status, and config path - #25

Merged
madtank merged 5 commits into
mainfrom
feature/outbound-delivery
Feb 9, 2026
Merged

madtank merged 5 commits into
mainfrom
feature/outbound-delivery

Conversation

@madtank

@madtank madtank commented Feb 6, 2026 •

Copy link
Copy Markdown
Member

Summary

  • JSON-RPC protocol fix: callAxTool() now sends proper MCP JSON-RPC tools/call requests to /mcp instead of the broken REST /tools/toolName endpoint. Handles both SSE streaming and plain JSON responses with extractToolResult() for MCP content envelope parsing.
  • Outbound interface alignment: sendText/sendMedia match Clawdbot's standard ChannelOutboundContext signature (to, text, cfg, replyToId, threadId, deps). Returns { channel: "ax-platform", ...result }.
  • Channel status interface: Added buildAccountSnapshot, buildChannelSummary, probeAccount so the dashboard shows proper Configured/Connected status. Probe only hits paxai.app for prod agents with 60s cache.
  • Config path fix: api.config is the full clawdbot.json — plugin config extracted from plugins.entries.ax-platform.config.
  • Default account: config.defaultAccountId returns first prod agent instead of first agent in list.
  • setup.sh: Now writes outbound config with auto-detected .ax-token.json file.

Test plan

  • ./setup.sh sync builds and restarts without errors
  • Gateway logs: agents=6, outbound=configured
  • Dashboard shows Configured: Yes for all accounts
  • Probe skips local agents, caches result for prod agents
  • Cron job triggers outbound delivery through ax-platform channel
  • Verify message appears in aX space after cron delivery

🤖 Generated with Claude Code

Adds proper outbound.sendText() implementation that uses the aX MCP
messages tool to send messages. This enables:

- Heartbeat delivery to ax-platform channel
- Cron job delivery with 'Deliver' checkbox
- Any agent reply routing to aX spaces

Configuration:
- outbound.tokenFile: Path to OAuth token JSON file
- outbound.mcpEndpoint: MCP server URL (default: https://mcp.paxai.app)
- outbound.defaultSpaceId: Default target space for delivery

The implementation reads the access token from the configured file
(or AX_ACCESS_TOKEN env var) and POSTs to the MCP messages tool.

Resolves: empty-heartbeat-file and 'Outbound not configured' errors
for cron jobs targeting ax-platform channel.
@claude

claude Bot commented Feb 6, 2026

Copy link
Copy Markdown

Test comment to verify permissions

@claude

claude Bot commented Feb 6, 2026

Copy link
Copy Markdown

Code Review

Found 1 issue that needs attention:

Type error in createDispatchHandler

File: extension/channel/ax-channel.ts
Line: 722

The config parameter of createDispatchHandler is typed as { backendUrl?: string }, which does not include an outbound property. However, line 722 accesses config.outbound:

https://github.com/ax-platform/ax-clawdbot-plugin/blob/8dc665e68ffa8b1959fc75956410aa80697d65fd/extension/channel/ax-channel.ts#L719-L723

This will cause a TypeScript compilation error:

Property 'outbound' does not exist on type '{ backendUrl?: string; }'.

Additionally, the outboundConfig variable captured here is never used within createDispatchHandler - it appears to be dead code.

Suggested fix: Either remove the unused line entirely, or update the type signature to include outbound?: OutboundConfig if this will be used in the future. Note that createAxChannel (line 574) was correctly updated to include outbound in its type signature.

clawdbot_cipher and others added 4 commits February 6, 2026 17:44
- Config now reads from channels.ax-platform.accounts (standard pattern)
- Falls back to plugins.entries.ax-platform.config.agents (legacy)
- Each agent handle becomes an account for multi-agent support
- Added status adapter for health checks (configured, accounts, sessions)
- Enhanced capabilities (media, threads, mentions)

This should fix 'configured: false' in gateway health checks and enable
proper delivery/heartbeat routing.

Gateway config example:
{
  channels: {
    'ax-platform': {
      accounts: {
        clawdbot_cipher: { agentId: 'uuid', secret: '...', handle: '@clawdbot_cipher', enabled: true }
      }
    }
  }
}
- Renamed clawdbot.plugin.json -> openclaw.plugin.json (required by OpenClaw)
- Added channelConfigSchema for channels.ax-platform.accounts pattern
- Added outbound config to plugin schema
- Bumped version to 0.3.0

This should fix 'Channel config schema unavailable' in gateway UI.
Clawdbot gateway looks for clawdbot.plugin.json, not openclaw.plugin.json.
The schema content added in previous commit is preserved.
- callAxTool now uses MCP JSON-RPC at /mcp instead of broken REST
  /tools/toolName endpoint. Handles both SSE and JSON responses.
- outbound sendText/sendMedia match Clawdbot's standard channel
  interface (to, text, cfg, replyToId, threadId, deps)
- Added status interface (buildAccountSnapshot, buildChannelSummary,
  probeAccount) so dashboard shows configured/connected status
- Fixed config path: api.config is full clawdbot.json, plugin config
  lives at plugins.entries.ax-platform.config
- Probe only hits paxai.app for prod agents, with 60s cache
- setup.sh now writes outbound config with auto-detected token file
- config.defaultAccountId returns first prod agent instead of first
  agent in list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@madtank madtank changed the title feat: implement outbound delivery for heartbeat/cron fix: outbound delivery with JSON-RPC, channel status, and config path Feb 9, 2026
@madtank

madtank commented Feb 9, 2026

Copy link
Copy Markdown
Member Author

✅ Reviewed by @clawdbot_cipher — LGTM, ship it.

This is a major upgrade. Reviewed the full diff (+451/-28 across 6 files). Key observations:

What's right:

  • JSON-RPC fix (callAxTool) is correct — proper tools/call method, handles both SSE streaming and plain JSON responses, extractToolResult unwraps MCP content envelopes. I've verified this works from my end (3 successful outbound tests today).
  • Config path fix is critical — api.config gives the full clawdbot.json, so extracting from plugins.entries["ax-platform"].config is the right move.
  • Outbound sendText/sendMedia properly match Clawdbot's ChannelOutboundContext signature. Good error handling with structured { channel, ok, error } returns.
  • Probe caching (60s TTL) is smart — prevents N MCP calls per dashboard status refresh. Only probes prod agents against paxai.app.
  • Token resolution fallback chain (tokenFile → env var) is solid.
  • sendMedia flattening — text + mediaUrl concatenation is pragmatic since the MCP messages tool doesn't have a native media attachment field yet. Works for now.

Minor observations (non-blocking):

  1. resolveOutboundToken reads the token file synchronously (readFileSync) inside an async function. Fine for now since it's a small file, but worth noting.
  2. probeCache is module-scoped via closure — cache survives until gateway restart. The 60s TTL handles staleness, but a probe failure also gets cached for 60s (could delay recovery detection).
  3. setup.sh finds the first .ax-token.json via glob — if multiple workspaces have token files, it'll pick whichever glob order gives first. Probably fine since most setups have one.

Confirmed working: Outbound delivery verified 3x today from my sandbox via mcporter → /mcp JSON-RPC. Both inbound (webhook dispatch) and outbound (sendText via MCP) are operational.

Merge it. 🚀

@madtank
madtank merged commit 30bd155 into main Feb 9, 2026
1 check passed
@madtank
madtank deleted the feature/outbound-delivery branch February 9, 2026 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant