Skip to content

docs: add docs/using-nats-cli.md + fix missing --reply-timeout flag#105

Merged
M64GitHub merged 3 commits into
mainfrom
nats-cli-docs
May 11, 2026
Merged

docs: add docs/using-nats-cli.md + fix missing --reply-timeout flag#105
M64GitHub merged 3 commits into
mainfrom
nats-cli-docs

Conversation

@M64GitHub
Copy link
Copy Markdown
Contributor

Summary

After §6.4 made the leading status=ack chunk mandatory, every nats req call to a prompt subject without --reply-timeout=30s exits after the ack alone (the CLI default is 300 ms — shorter than the gap between the leading ack and the model's first response). Four prompt examples in this repo were missing the flag.

This PR:

  1. Adds docs/using-nats-cli.md — a canonical cookbook for driving an agent from the nats CLI. Covers discovery, heartbeats, prompting (text + JSON envelope + attachments), the three load-bearing flags and why each one matters, status snapshots, headless control-plane RPCs, and a gotchas table. Consolidates content that was copy-pasted across four agent READMEs.
  2. Fixes the four prompt examples missing --reply-timeout=30s:
    • client-sdk/python/README.md
    • agents/claude-code/README.md
    • agents/open-agent/README.md
    • examples/open-agent-vercel/README.md
  3. Adds a pointer from the main README to the new cookbook.

Intentionally NOT changed

These nats req calls don't stream — they're single-reply RPCs — so --reply-timeout is moot:

  • Discovery: $SRV.INFO.agents, $SRV.PING.agents (in README.md, agents/{pi,openclaw,claude-code}/README.md).
  • Status: agents.status.* (single heartbeat-shaped reply).
  • Control-plane: agents.{spawn,list,stop}.* (single JSON reply) in the headless examples.

If you'd rather have the flag added uniformly to all nats req calls regardless, let me know and I'll widen the sweep — it'd be a redundant no-op on the discovery/status/control-plane calls but harmless.

Test plan

  • Reviewer bot has no findings
  • Render docs/using-nats-cli.md on GitHub — verify the table formatting and code blocks survive
  • Spot-check one prompt example end-to-end: nats req agents.prompt.pi.<owner>.<session> "hi" --replies=0 --reply-timeout=30s --timeout=60s actually streams chunks past the ack

🤖 Generated with Claude Code

A canonical cookbook for driving an agent from the `nats` CLI.
Consolidates the troubleshooting paragraphs that were copy-pasted
across four agent READMEs.

Also fixes four `nats req` prompt examples that were missing
`--reply-timeout=30s`. After §6.4 made the leading `status=ack`
chunk mandatory, every `nats req` call to a prompt subject without
this flag exits after the ack alone (default `--reply-timeout` is
300 ms — shorter than the gap between the ack and the model's
first response).

Fixed examples:
- client-sdk/python/README.md
- agents/claude-code/README.md
- agents/open-agent/README.md
- examples/open-agent-vercel/README.md

Discovery (`\$SRV.INFO.agents`), status (`agents.status.*`), and
control-plane RPCs (`agents.{spawn,list,stop}.*`) intentionally
left alone — they're single-reply, not streamed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@synadia-claude-reviewer
Copy link
Copy Markdown

synadia-claude-reviewer Bot commented May 11, 2026

Claude finished @M64GitHub's task in 4m 38s —— View job


PR Review

  • Gather context and read changed files
  • Review docs/using-nats-cli.md for correctness and protocol compliance
  • Review README flag fixes
  • Check for any issues with the main README pointer
  • Post findings

Summary

The four --reply-timeout=30s fixes are correct and necessary — all four call sites were missing the flag that guards against the §6.4 leading-ack gap. No issues there.

The new cookbook (docs/using-nats-cli.md) is thorough and mostly accurate, but there is one factual error in the wire diagram that needs to be fixed before merge:

Incorrect keepalive status value (inline comment posted at line 88)

The wire diagram shows {"type":"status","data":"keepalive"} for the periodic keep-alive, but both SDKs emit {"type":"status","data":"ack"} — the same token as the leading ack. There is no distinct keepalive status value on the wire. This is clearly documented in both SDK codebases:

  • TS: agent-sdk/typescript/src/service.ts line 19 comment
  • Python: agent-sdk/python/src/synadia_ai/agent_service/service.py lines 97–99, 208

Two secondary notes (not blocking, but worth a look):

  1. --replies=0 doesn't "recognize" stream termination — the gotcha table says "One of them [--replies=0 or --wait-for-empty] is needed for the CLI to recognize stream termination." This is only accurate for --wait-for-empty. With --replies=0, the CLI never recognizes the empty-body terminator as special — it simply waits until --reply-timeout fires after the last chunk (30s dead wait). agents/pi/README.md and agents/openclaw/README.md both say --wait-for-empty is required precisely because of this, while this cookbook presents --replies=0 as equivalent. Consider adding a note that --replies=0 terminates via timeout (30s after last chunk) while --wait-for-empty exits immediately at the terminator.

  2. "hangs forever" gotcha — With the recommended --timeout=60s in place, the CLI won't hang forever; it exits after --reply-timeout fires. The "forever" language only holds if the user also omits --timeout, which isn't the scenario described in the gotcha (the user presumably followed the minimum viable invocation above). Minor wording nit.

Comment thread docs/using-nats-cli.md Outdated
{"type":"status","data":"ack"} ← mandatory §6.4 leading chunk, sent instantly
{"type":"response","data":"Sure, here..."} ← model output (one or more)
{"type":"response","data":" are the files"} ← ...
{"type":"status","data":"keepalive"} ← optional periodic keep-alive
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong status value for keepalive. Both SDKs emit {"type":"status","data":"ack"} for the periodic mid-stream keep-alive — the same value as the leading ack. There is no distinct "keepalive" token on the wire.

From agent-sdk/typescript/src/service.ts (comment line 19):

{"type":"status","data":"ack"} every keepaliveIntervalS seconds while the prompt handler is running

From agent-sdk/python/src/synadia_ai/agent_service/service.py (docstring line 208):

{"type":"status","data":"ack"} every keepalive_interval_s

The line should read:

Suggested change
{"type":"status","data":"keepalive"} ← optional periodic keep-alive
{"type":"status","data":"ack"} ← optional periodic keep-alive (same "ack" token as the leading chunk)

M64GitHub and others added 2 commits May 11, 2026 23:56
- Wire diagram: the periodic keep-alive emits {"type":"status","data":"ack"},
  not "keepalive" — same token as the leading chunk. Both SDKs do this
  (see agent-sdk/typescript/src/service.ts:19 and
  agent-sdk/python/src/synadia_ai/agent_service/service.py:208).
- Clarify --wait-for-empty vs --replies=0: --wait-for-empty exits
  immediately at the protocol terminator; --replies=0 doesn't know about
  the terminator and waits the full --reply-timeout (30s dead tail).
  Not equivalent.
- "Hangs forever" gotcha → "sits idle for 30 s before exiting" — with
  --timeout in place the CLI does exit; the wait is just dead.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@M64GitHub
Copy link
Copy Markdown
Contributor Author

@claude - please review again

@synadia-claude-reviewer
Copy link
Copy Markdown

synadia-claude-reviewer Bot commented May 11, 2026

Claude finished @M64GitHub's task in 1m 24s —— View job


PR Review

  • Gather context
  • Read docs/using-nats-cli.md (current state)
  • Verify SDK sources for keepalive wire behavior
  • Review all four README flag fixes
  • Check main README pointer

Summary

All three findings from the previous review have been addressed. The PR is clean and ready to merge.


Previous findings — resolved

1. Keepalive status value (was blocking) ✅ Fixed

docs/using-nats-cli.md line 93 now correctly reads:

{"type":"status","data":"ack"}              ← optional periodic keep-alive (same "ack" token as the leading chunk)

This matches both SDK sources:

  • TS agent-sdk/typescript/src/service.ts:19: "{"type":"status","data":"ack"} every keepaliveIntervalS seconds while the prompt handler is running"
  • Python agent-sdk/python/src/synadia_ai/agent_service/service.py:208: "{"type":"status","data":"ack"} every keepalive_interval_s"

2. --replies=0 termination behavior (was secondary) ✅ Fixed

Lines 58–70 now clearly separate the two modes:

  • --wait-for-empty — exits immediately on the protocol terminator
  • --replies=0 — waits the full --reply-timeout (30 s dead wait after last chunk)

The recommendation to prefer --wait-for-empty is explicit. The gotchas table (line 135) adds a dedicated row for the "sits idle for 30 s" symptom with the correct fix.

3. "hangs forever" wording (was secondary) ✅ Fixed

The gotchas table row now reads "sits idle for 30 s before exiting" — accurate for the scenario where --timeout is in place.


The four --reply-timeout=30s fixes

All four prompt examples correctly updated:

File Invocation
agents/claude-code/README.md:99 --replies=0 --reply-timeout=30s --timeout=90s
agents/open-agent/README.md:57 --replies=0 --reply-timeout=30s --timeout=5m
client-sdk/python/README.md:172 --replies=0 --reply-timeout=30s --timeout=60s
examples/open-agent-vercel/README.md:82 --replies=0 --reply-timeout=30s --timeout=5m

The client-sdk/python/README.md also adds a helpful inline pointer to docs/using-nats-cli.md.


Main README pointer

README.md now includes:

To prompt an agent directly from the CLI (no SDK), pass three flags — --replies=0 --reply-timeout=30s --timeout=60s. The full CLI cookbook (prompts, attachments, status, control-plane, gotchas) lives at docs/using-nats-cli.md.

Correctly placed, concise, and accurate.


No remaining issues. The cookbook is technically accurate, the flag fixes are correct, and the secondary findings about --replies=0 behavior and wording have been addressed cleanly.

@M64GitHub M64GitHub merged commit a5bf9fc into main May 11, 2026
6 checks passed
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