Skip to content

feat: cueapi message-to <name> + agents --online-only + describe alias#39

Closed
mikemolinet wants to merge 1 commit into
mainfrom
feat/cli-message-to-and-agents-aliases
Closed

feat: cueapi message-to <name> + agents --online-only + describe alias#39
mikemolinet wants to merge 1 commit into
mainfrom
feat/cli-message-to-and-agents-aliases

Conversation

@mikemolinet
Copy link
Copy Markdown
Collaborator

Summary

Implements the CLI portion of the agent-directory productization PRD — Surface 3, items locked in CTO-AGENT-DIRECTORY-PRD-SEC-V2-RESPONSE-ACK.

What ships

cueapi message-to <agent-name> <body> — the universal inter-agent comm primitive

The PRD's stated goal: agents address peers by stable name; the 6-field cue-fire incantation goes away from agent code. This command is the CLI realization. Replaces the per-agent bash-script anti-pattern (Scripts/cma-reply.sh etc.) with a single canonical CLI command.

# Simple
cueapi message-to alice "ack on the design review"

# Multi-line via stdin
echo "longer message" | cueapi message-to alice -

# With token-derived subject + thread metadata
cueapi message-to alice "ack" --token PR-REVIEW-V1 --expects-reply

# Sender from env var (one-time setup per agent session)
CUEAPI_MY_AGENT_SLUG=cueapi-secondary cueapi message-to alice "hi"

Behavior pinned by tests:

  • Pre-flight resolve of the recipient by default — typo'd names fail fast with Unknown agent 'foo'. Run cueapi agents list to see available agents. instead of being silently routed somewhere bad. --skip-resolve opts out for callers who want to save the API call.
  • --from defaults from $CUEAPI_MY_AGENT_SLUG — every agent sets the env once at session boot, the CLI auto-fills.
  • --token auto-fills --subject as [TOKEN] <first-body-line> and stashes in metadata.token for thread traceability. Explicit --subject wins.
  • --idempotency-key max 255 chars enforced client-side (matches server's hard limit).
  • --priority Click IntRange(1, 5) — bad values fail fast without HTTP round-trip.
  • Server signals surfaced: dedup-hit (200 instead of 201) renders "Idempotency-Key dedup hit" UI copy; X-CueAPI-Priority-Downgraded: true rendered when receiver-pair limits apply.

cueapi agents list --online-only

Convenience alias for --status online. Mutually exclusive with --status (raises UsageError before any HTTP call).

cueapi agents describe <ref>

Verb alias for cueapi agents get <ref> — same Click command registered under both names. Per the PRD's discovery vocabulary ("describe this agent to me" reads better than "get"). Both verbs invoke the same callback, same options, same behavior — adding new options to agents_get auto-applies to agents describe.

Skipped from PRD scope

cueapi agents roster (wraps GET /v1/agents/roster) is gated on cueapi shipping the roster endpoint. Will follow in a small PR once that endpoint lands.

Tests

15 new (133 → 148 total). Mock-based, mirrors the patterns established in cueapi-cli #28 + #29.

Test class Coverage
--online-only help text, mutex with --status, translates to status=online query param
agents describe alias visible in group help, accepts ref
message-to help all flags surfaced
message-to env CUEAPI_MY_AGENT_SLUG auto-fills --from
message-to resolve pre-flight GET /agents/<name> happens before POST
message-to unknown 404 path produces clear error + suggests agents list; no POST attempted
message-to --skip-resolve bypasses pre-flight
message-to --token auto-fills subject + stashes in metadata.token
message-to --token + --subject explicit subject wins
message-to --idempotency-key length cap enforced client-side
message-to --priority Click IntRange validation

All 148 pass locally.

No hosted-PR dependency

All endpoints already shipped on prod via Phase 12.1 messaging primitive. Pure CLI ergonomics layer.

Migration story

cue-mac-app shipped Scripts/cma-reply.sh this morning as their prevention layer. Per CTO direction (CTO-AGENT-DIRECTORY-PRD-SEC-V2-RESPONSE-ACK), once this PR ships, cma-reply.sh becomes a transitional artifact:

  • Phase A: ship cueapi message-to (this PR). Existing scripts keep working.
  • Phase B: rewrite cma-reply.sh and equivalents as 1-line shims that call cueapi message-to. Same script names (back-compat for CLAUDE.md instructions) but internals migrate transparently.
  • Phase C: deprecate the shims when CLAUDE.mds have been updated. Scripts dir gets simpler over time, not more cluttered.

CTO is fanning the migration plan to cue-mac-app separately.

🤖 Generated with Claude Code

Per the agent-directory productization PRD (https://trydock.ai/mike/agent-directory-productization-prd),
this adds the CLI surface for the universal inter-agent comm primitive
the PRD calls for, plus two `agents` group conveniences.

## `cueapi message-to <agent-name> <body>` — universal inter-agent comm

The PRD's stated goal: agents address peers by stable name; the 6-field
cue-fire incantation goes away from agent code. This command is the CLI
realization of that.

Hides the messaging-primitive routing details (X-Cueapi-From-Agent
header, Idempotency-Key header, /v1/messages POST shape) so callers
don't need to remember them. Replaces the per-agent bash-script
anti-pattern (cma-reply.sh and siblings) with a single canonical CLI
command.

Behavior:

- AGENT_NAME pre-flight: by default, `GET /v1/agents/<name>` is called
  before the POST to validate the recipient exists. Typo'd names fail
  fast with a clear error ("Unknown agent 'foo'. Run `cueapi agents
  list` to see available agents.") instead of being silently routed.
  --skip-resolve opts out of the pre-flight for callers who want to
  save the API call.

- BODY positional or stdin: `cueapi message-to alice "hi"` OR
  `echo "msg" | cueapi message-to alice` OR
  `cueapi message-to alice -` (explicit stdin marker). Useful for
  multi-line messages.

- --from defaults from $CUEAPI_MY_AGENT_SLUG env var. Required either
  via flag or env. The PRD's vision is each agent sets the env once at
  session boot and the CLI auto-fills it from there.

- --token auto-fills subject as `[TOKEN] <first-body-line>` and stashes
  in metadata.token for thread traceability. Matches the existing
  cue-fire convention used by PM/CTO threads. Explicit --subject takes
  precedence.

- --idempotency-key max 255 enforced client-side. Same client-side cap
  as `cueapi messages send` — fails fast.

- --priority click.IntRange(1, 5). Same validation as
  `messages send`.

- Surfaces server's X-CueAPI-Priority-Downgraded response header when
  receiver-pair limits apply.

- 200 vs 201 distinction surfaced as "Idempotency-Key dedup hit" UI
  copy on 200; matches messages send.

## `cueapi agents list --online-only`

One-line alias for `--status online`. Mutually exclusive with --status
(raises UsageError before any HTTP call).

## `cueapi agents describe <ref>`

Verb alias for `cueapi agents get <ref>` — same Click command
registered under both names (via `agents.add_command(agents_get,
name="describe")`). Per the agent-directory PRD's discovery vocabulary
("describe this agent to me"). Both verbs invoke the same callback,
same options, same behavior; new options added to `agents_get`
auto-apply to `agents describe`.

## Tests

15 new (133 → 148 total):

- `--online-only` flag in help, mutex with --status, translates to
  status=online query param
- `agents describe` alias visible in group help, accepts ref
- `message-to` help shows all flags
- env-var `CUEAPI_MY_AGENT_SLUG` auto-fills --from
- pre-flight resolve happens before POST
- unknown recipient → clear error + no POST attempted
- --skip-resolve skips the pre-flight GET
- --token auto-fills subject + stashes in metadata
- --idempotency-key length cap enforced client-side
- --priority Click IntRange validation
- explicit --subject wins over token-derived

## Skipped from PRD scope

`cueapi agents roster` (wraps GET /v1/agents/roster) is gated on cueapi
shipping the roster endpoint. Will follow in a small PR once that
endpoint lands. Rest of Surface 3 work tracked under PRD's Phase A
status board.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@govindkavaturi-art govindkavaturi-art enabled auto-merge (squash) May 5, 2026 17:28
@mikemolinet
Copy link
Copy Markdown
Collaborator Author

Superseded by #40 — opened 3 min later with the broader scope (message-to + --online-only filter + describe alias all in one PR). Closing this as duplicate.

@mikemolinet mikemolinet closed this May 5, 2026
auto-merge was automatically disabled May 5, 2026 23:13

Pull request was closed

mikemolinet added a commit that referenced this pull request May 11, 2026
…out (#52)

Mike body-verify directive 2026-05-11 — Phase 2 SDK auto-verify layer
for cueapi-cli. Sibling to cueapi-python PR #39 (auto_verify default-
on at the resource layer). Wire shape locked via cueapi/cueapi-core PR
#86 + cueapi/cueapi PR #795 (Layer 1 substrate echo-back, merged
22:55Z).

Changes:

cueapi/cli.py:
- _first_divergence_byte(a, b) — pure helper returning byte index of
  first differing position; -1 when one is a proper prefix of the
  other.
- _emit_body_verify_mismatch_diagnostic — pretty-prints sent vs
  received diff (first 200 chars each side) + byte position + msg_id
  + actionable mitigation hint. All to stderr.
- messages_send + message_to: new --no-verify flag (default verify-on).
  Sends X-CueAPI-Verify-Echo: true header; on 201 response, diffs
  m["body_received"] against sent body; on mismatch emits diagnostic +
  ctx.exit(7) (distinct from generic failure exit codes 1-5).
- Backward-compat: when substrate omits body_received field (pre-
  Layer-1 deploy), no-op + return normally.

tests/test_cli.py:
- 5 new Phase 2 tests pin: default-on header, --no-verify omits
  header, byte-identical echo passes, mismatched echo exits 7 with
  MISMATCH in output, no-op when substrate omits echo field.
- Plus 9 prior Phase 3 tests preserved.
- Plus 45 prior existing tests preserved.
- 205 tests in suite; 65 messaging-related; all pass.

Exit code 7 distinct from generic 1-5 so callers can branch on
verify-mismatch specifically (CI workflows can retry with
--message-file).

CHANGELOG entry under [Unreleased].

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant