feat(cli): add --url flag for agent command

This option allows specifying a custom Gateway WebSocket URL (e.g., ws://gateway:18789), which is critical for Docker environments where localhost resolution differs between containers.

Changes:

- Add --url/-u option to agent command

- Update gateway connection logic to prioritize --url flag

- Add documentation and tests
This commit is contained in:
Dan Lewis 2026-01-26 21:00:04 -09:00
parent 0b1c8db0ca
commit 3807a53ca2
5 changed files with 78 additions and 16 deletions

View File

@ -1,10 +1,10 @@
---
summary: "CLI reference for `moltbot agent` (send one agent turn via the Gateway)"
summary: "CLI reference for `clawdbot agent` (send one agent turn via the Gateway)"
read_when:
- You want to run one agent turn from scripts (optionally deliver reply)
---
# `moltbot agent`
# `clawdbot agent`
Run an agent turn via the Gateway (use `--local` for embedded).
Use `--agent <id>` to target a configured agent directly.
@ -12,11 +12,26 @@ Use `--agent <id>` to target a configured agent directly.
Related:
- Agent send tool: [Agent send](/tools/agent-send)
## Options
| Flag | Description |
|------|-------------|
| `--url <url>` | Gateway WebSocket URL (for Docker setups where gateway is on a different host/container) |
| `--local` | Run embedded agent locally instead of via gateway |
| `--deliver` | Send the agent's reply back to the channel |
| `--json` | Output result as JSON |
| `--timeout <seconds>` | Override agent command timeout |
See `clawdbot agent --help` for the full list of options.
## Examples
```bash
moltbot agent --to +15555550123 --message "status update" --deliver
moltbot agent --agent ops --message "Summarize logs"
moltbot agent --session-id 1234 --message "Summarize inbox" --thinking medium
moltbot agent --agent ops --message "Generate report" --deliver --reply-channel slack --reply-to "#reports"
clawdbot agent --to +15555550123 --message "status update" --deliver
clawdbot agent --agent ops --message "Summarize logs"
clawdbot agent --session-id 1234 --message "Summarize inbox" --thinking medium
clawdbot agent --agent ops --message "Generate report" --deliver --reply-channel slack --reply-to "#reports"
# Docker: connect CLI container to gateway container
docker compose run --rm clawdbot-cli agent --agent main --message "test" --url ws://clawdbot-gateway:18789
```

View File

@ -1,11 +1,11 @@
---
summary: "Direct `moltbot agent` CLI runs (with optional delivery)"
summary: "Direct `clawdbot agent` CLI runs (with optional delivery)"
read_when:
- Adding or modifying the agent CLI entrypoint
---
# `moltbot agent` (direct agent runs)
# `clawdbot agent` (direct agent runs)
`moltbot agent` runs a single agent turn without needing an inbound chat message.
`clawdbot agent` runs a single agent turn without needing an inbound chat message.
By default it goes **through the Gateway**; add `--local` to force the embedded
runtime on the current machine.
@ -21,7 +21,7 @@ runtime on the current machine.
- Output:
- default: prints reply text (plus `MEDIA:<url>` lines)
- `--json`: prints structured payload + metadata
- Optional delivery back to a channel with `--deliver` + `--channel` (target formats match `moltbot message --target`).
- Optional delivery back to a channel with `--deliver` + `--channel` (target formats match `clawdbot message --target`).
- Use `--reply-channel`/`--reply-to`/`--reply-account` to override delivery without changing the session.
If the Gateway is unreachable, the CLI **falls back** to the embedded local run.
@ -29,16 +29,20 @@ If the Gateway is unreachable, the CLI **falls back** to the embedded local run.
## Examples
```bash
moltbot agent --to +15555550123 --message "status update"
moltbot agent --agent ops --message "Summarize logs"
moltbot agent --session-id 1234 --message "Summarize inbox" --thinking medium
moltbot agent --to +15555550123 --message "Trace logs" --verbose on --json
moltbot agent --to +15555550123 --message "Summon reply" --deliver
moltbot agent --agent ops --message "Generate report" --deliver --reply-channel slack --reply-to "#reports"
clawdbot agent --to +15555550123 --message "status update"
clawdbot agent --agent ops --message "Summarize logs"
clawdbot agent --session-id 1234 --message "Summarize inbox" --thinking medium
clawdbot agent --to +15555550123 --message "Trace logs" --verbose on --json
clawdbot agent --to +15555550123 --message "Summon reply" --deliver
clawdbot agent --agent ops --message "Generate report" --deliver --reply-channel slack --reply-to "#reports"
# Docker: connect CLI container to gateway container
docker compose run --rm clawdbot-cli agent --agent main --message "test" --url ws://clawdbot-gateway:18789
```
## Flags
- `--url <url>`: Gateway WebSocket URL (for Docker setups where gateway is on a different host/container)
- `--local`: run locally (requires model provider API keys in your shell)
- `--deliver`: send the reply to the chosen channel
- `--channel`: delivery channel (`whatsapp|telegram|discord|googlechat|slack|signal|imessage`, default: `whatsapp`)

View File

@ -45,6 +45,7 @@ export function registerAgentCommands(program: Command, args: { agentChannelOpti
"--timeout <seconds>",
"Override agent command timeout (seconds, default 600 or config value)",
)
.option("--url <url>", "Gateway WebSocket URL (defaults to gateway.remote.url when configured)")
.addHelpText(
"after",
() =>
@ -66,6 +67,10 @@ ${formatHelpExamples([
'moltbot agent --agent ops --message "Generate report" --deliver --reply-channel slack --reply-to "#reports"',
"Send reply to a different channel/target.",
],
[
'docker compose run --rm clawdbot-cli agent --agent main --message "test" --url ws://clawdbot-gateway:18789',
"Connect from CLI container to gateway container (Docker).",
],
])}
${theme.muted("Docs:")} ${formatDocsLink("/cli/agent", "docs.molt.bot/cli/agent")}`,

View File

@ -123,4 +123,40 @@ describe("agentCliCommand", () => {
fs.rmSync(dir, { recursive: true, force: true });
}
});
it("passes url option to callGateway", async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "clawdbot-agent-cli-"));
const store = path.join(dir, "sessions.json");
mockConfig(store);
vi.mocked(callGateway).mockResolvedValue({
runId: "idem-1",
status: "ok",
result: {
payloads: [{ text: "hello" }],
meta: { stub: true },
},
});
try {
await agentCliCommand(
{
message: "hi",
to: "+1555",
url: "ws://clawdbot-gateway:18789",
},
runtime,
);
expect(callGateway).toHaveBeenCalledTimes(1);
expect(callGateway).toHaveBeenCalledWith(
expect.objectContaining({
url: "ws://clawdbot-gateway:18789",
}),
);
expect(agentCommand).not.toHaveBeenCalled();
} finally {
fs.rmSync(dir, { recursive: true, force: true });
}
});
});

View File

@ -50,6 +50,7 @@ export type AgentCliOpts = {
runId?: string;
extraSystemPrompt?: string;
local?: boolean;
url?: string;
};
function parseTimeoutSeconds(opts: { cfg: ReturnType<typeof loadConfig>; timeout?: string }) {
@ -118,6 +119,7 @@ export async function agentViaGatewayCommand(opts: AgentCliOpts, runtime: Runtim
},
async () =>
await callGateway<GatewayAgentResponse>({
url: opts.url,
method: "agent",
params: {
message: body,