Skip to content

feat: add cueapi agents command group (messaging primitive — identity + inbox + sent)#28

Merged
govindkavaturi-art merged 1 commit intomainfrom
feat/cli-agents-command-group
May 4, 2026
Merged

feat: add cueapi agents command group (messaging primitive — identity + inbox + sent)#28
govindkavaturi-art merged 1 commit intomainfrom
feat/cli-agents-command-group

Conversation

@mikemolinet
Copy link
Copy Markdown
Collaborator

Summary

First half of the messaging-primitive CLI port. Closes the Messaging primitive endpoints_missing entry in cueapi-cli #25's manifest by exposing the entire /v1/agents API surface as a cueapi agents command group.

The complementary cueapi messages group (send / get / read / ack for the message lifecycle) ships in a follow-up PR for review-burden reasons (per CTO call to keep parity-port PRs small).

Commands shipped (9)

Command Endpoint Notes
cueapi agents create POST /v1/agents Webhook secret is shown ONLY in this response when --webhook-url is set; UI copy says "save now — only shown once"
cueapi agents list GET /v1/agents filters: --status / --include-deleted / --limit / --offset
cueapi agents get GET /v1/agents/{ref} renders metadata pretty-printed; null webhook_url renders as — (poll-only) so push-vs-poll is visible at a glance
cueapi agents update PATCH /v1/agents/{ref} --webhook-url and --clear-webhook-url are mutually exclusive; the latter sends literal JSON null
cueapi agents delete DELETE /v1/agents/{ref} soft delete; confirmation prompt unless --yes
cueapi agents webhook-secret get GET /v1/agents/{ref}/webhook-secret reveal current secret
cueapi agents webhook-secret regenerate POST /v1/agents/{ref}/webhook-secret/regenerate confirmation warns current secret will be revoked immediately
cueapi agents inbox GET /v1/agents/{ref}/inbox filters: --state / --limit / --offset
cueapi agents sent GET /v1/agents/{ref}/sent filters: --limit / --offset

Design notes worth flagging

  • --clear-webhook-url sends literal JSON null, not field omission. The server uses model_fields_set to disambiguate "field omitted = no change" vs "field explicitly null = clear." The CLI matches by sending {"webhook_url": null} in the patch body when --clear-webhook-url is present. Pinned by a dedicated test so a future refactor can't silently collapse the two semantics.

  • --include-deleted is a flag, only sent when True. Same pattern as executions list --has-evidence (PR feat: add executions-list filters — outcome-state / result-type / has-evidence / triggered-by #27): omit when False rather than send false (which would mean the same thing server-side but adds URL noise).

  • --webhook-url and --clear-webhook-url are mutually exclusive. Click UsageError enforced before any HTTP call.

  • Webhook-secret one-time view. Both agents create (when --webhook-url is set) and agents webhook-secret regenerate print the secret with explicit copy: "save now — only shown once." Matches the server's behavior of populating webhook_secret only on those two responses.

Tests

24 new (36 → 60 total). Mock-based body / params capture mirroring PR #26 + #27's _FakeClient pattern. Pinned behaviors:

  • agents_create minimal vs all-optional body shape
  • --include-deleted only sent when True
  • --clear-webhook-url sends explicit null (key present, value None)
  • --webhook-url + --clear-webhook-url mutex enforced
  • Delete confirmation prompt path + abort path
  • Webhook-secret one-time-view UI copy is rendered
  • Inbox / sent rendering of common message shape

All 60 pass locally.

No hosted-PR dependency

All 9 endpoints already shipped on prod via Phase 12.1 messaging primitive (per MEMORY.md). Pure CLI catch-up.

Test plan

  • python3 -m pytest tests/test_cli.py -q → 60 passed
  • Manual smoke against staging: cueapi agents create --display-name "test" → confirm 201 + slug derived; cueapi agents list → confirm renders; cueapi agents update <ref> --clear-webhook-url → confirm webhook_url cleared on subsequent get

Parity Impact

Closes endpoints_missing.Messaging primitive from cueapi-cli #25's parity-manifest.json (partial — agents portion only). Manifest update follows after #25 merges to main, alongside the cueapi messages follow-up PR.

🤖 Generated with Claude Code

…ty + inbox + sent)

Closes the cueapi-cli #25 manifest gap on the messaging primitive's identity
surface (POST /v1/agents + 8 sibling endpoints). v1 of the messaging-primitive
CLI work; the `cueapi messages` group (send/get/read/ack) ships in a follow-up
PR for review-burden reasons.

Commands shipped (9 total):

- `cueapi agents create --display-name X [--slug Y] [--webhook-url Z]
  [--metadata '{...}']` — POST /v1/agents. Webhook secret is shown ONLY in
  this response when --webhook-url is set; subsequent reads omit it. UI
  copy explicitly says "save now — only shown once."
- `cueapi agents list [--status online/offline/away] [--include-deleted]
  [--limit N] [--offset N]` — GET /v1/agents.
- `cueapi agents get <ref> [--include-deleted]` — GET /v1/agents/{ref}.
  Renders metadata pretty-printed; null webhook_url is rendered as
  "— (poll-only)" so the user sees push vs poll at a glance.
- `cueapi agents update <ref> [--display-name] [--webhook-url |
  --clear-webhook-url] [--status] [--metadata]` — PATCH /v1/agents/{ref}.
  --webhook-url and --clear-webhook-url are mutually exclusive; the latter
  sends literal JSON null, matching the server's model_fields_set
  disambiguation (omit = no change vs explicit-null = clear).
- `cueapi agents delete <ref> [--yes]` — DELETE /v1/agents/{ref}. Soft
  delete. Confirmation prompt unless --yes.
- `cueapi agents webhook-secret get <ref>` — reveals the current secret
  (200 path).
- `cueapi agents webhook-secret regenerate <ref> [--yes]` — POST
  /v1/agents/{ref}/webhook-secret/regenerate. Confirmation prompt warns
  the current secret will be revoked immediately. Returns the new secret
  one-time, same UI copy as create.
- `cueapi agents inbox <ref> [--state queued/delivered/etc] [--limit]
  [--offset]` — GET /v1/agents/{ref}/inbox. Polling endpoint.
- `cueapi agents sent <ref> [--limit] [--offset]` — GET /v1/agents/{ref}/sent.

Tests: 24 new (36 → 60 total). Mock-based body / params capture mirroring
PR #26 + #27's _FakeClient pattern. Pinned behaviors:

- --include-deleted only sent when True (omits when False) — same pattern
  as `executions list --has-evidence`.
- --clear-webhook-url sends `webhook_url: null` literally (not omits).
- --webhook-url + --clear-webhook-url mutex enforced at click.UsageError.
- Confirmation prompt path on delete + webhook-secret regenerate.
- Webhook-secret one-time-view UI copy is rendered.

No hosted-PR dependency — all 9 endpoints already shipped on prod (Phase
12.1 messaging primitive). Pure CLI catch-up to existing server surface.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Copy link
Copy Markdown
Member

@govindkavaturi-art govindkavaturi-art left a comment

Choose a reason for hiding this comment

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

Comprehensive cueapi agents group port. Quality details: webhook-secret one-time-view UX (save now — only shown once), --include-deleted only sent when true (URL hygiene), idiomatic click patterns. Approve.

@govindkavaturi-art govindkavaturi-art merged commit ab0c4d2 into main May 4, 2026
4 checks passed
mikemolinet added a commit that referenced this pull request May 4, 2026
…et/regenerate`

Drains 3 entries from cueapi-cli #25's `endpoints_missing` plus a bonus
DELETE that wasn't in the manifest:

- GET /v1/workers → `cueapi workers list`
- DELETE /v1/workers/{id} → `cueapi workers delete <id>`
- GET /v1/auth/webhook-secret → `cueapi key webhook-secret get`
- POST /v1/auth/webhook-secret/regenerate → `cueapi key webhook-secret regenerate`

Two new / extended groups: `cueapi workers` (top-level) + `cueapi key
webhook-secret` (nested under existing `key`).

`regenerate` automatically sends `X-Confirm-Destructive: true` header
(server-required); pinned by test_key_webhook_secret_regenerate_sends_destructive_header.
404 on `key webhook-secret get` produces a helpful error pointing
messaging-primitive-only users at the per-agent path.

Tests: 11 new (60 → 71 total). Reuses _FakeResp from agents tests added in #28; adds
_WSClient capture class for header-sensitive tests.

Skipped from manifest: POST /v1/worker/heartbeat (manifest itself notes
it's redundant with cueapi-worker package).

No hosted-PR dependency.

Rebased against main 2026-05-04 (post-#28 agents-group merge).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
govindkavaturi-art pushed a commit that referenced this pull request May 4, 2026
…et/regenerate` (#33)

Drains 3 entries from cueapi-cli #25's `endpoints_missing` plus a bonus
DELETE that wasn't in the manifest:

- GET /v1/workers → `cueapi workers list`
- DELETE /v1/workers/{id} → `cueapi workers delete <id>`
- GET /v1/auth/webhook-secret → `cueapi key webhook-secret get`
- POST /v1/auth/webhook-secret/regenerate → `cueapi key webhook-secret regenerate`

Two new / extended groups: `cueapi workers` (top-level) + `cueapi key
webhook-secret` (nested under existing `key`).

`regenerate` automatically sends `X-Confirm-Destructive: true` header
(server-required); pinned by test_key_webhook_secret_regenerate_sends_destructive_header.
404 on `key webhook-secret get` produces a helpful error pointing
messaging-primitive-only users at the per-agent path.

Tests: 11 new (60 → 71 total). Reuses _FakeResp from agents tests added in #28; adds
_WSClient capture class for header-sensitive tests.

Skipped from manifest: POST /v1/worker/heartbeat (manifest itself notes
it's redundant with cueapi-worker package).

No hosted-PR dependency.

Rebased against main 2026-05-04 (post-#28 agents-group merge).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
…age lifecycle)

Closes the messages portion of cueapi-cli #25's `Messaging primitive`
endpoints_missing entry. Pairs with the already-merged #28 (agents group).

Commands shipped:

- `cueapi messages send` — POST /v1/messages with X-Cueapi-From-Agent +
  Idempotency-Key headers. Surfaces dedup-hit (200) and priority-downgrade
  signal explicitly.
- `cueapi messages get` — GET /v1/messages/{id}.
- `cueapi messages read` — POST /v1/messages/{id}/read (idempotent).
- `cueapi messages ack` — POST /v1/messages/{id}/ack (terminal).

Pinned by tests:
- --from goes in HEADER, not body (server's MessageCreate is extra="forbid")
- --expects-reply flag only sent when True
- --priority validated by click.IntRange(1, 5)
- --idempotency-key max 255 chars enforced client-side
- 409 idempotency-key-conflict produces helpful guidance

Tests: 18 new (60 → 78 total).

No hosted-PR dependency.

Rebased against main 2026-05-04 (post-#28 agents-group merge).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
…, verification, on-success-fire, status)

Drains `cueapi create` + `cueapi update` `command_drift.missing_flags`
entries from cueapi-cli #25's parity manifest. JSON-pass-through flags
mapping to existing CueCreate / CueUpdate schema fields.

Both `create` and `update`:
- --delivery (JSON) / --alerts (JSON) / --verification (JSON)
- --catch-up (Click choice: run_once_if_missed / skip_missed / replay_all)
- --on-success-fire (cue ID for 1:1 chaining)

`update` only:
- --status (Click choice: active / paused; alternative to pause/resume)
- --clear-on-success-fire (sends literal JSON null; mutually exclusive with --on-success-fire)

Click Choice flags fail fast client-side (no HTTP round-trip on bad
values). --clear-on-success-fire pinned to send null literally (server's
model_fields_set sentinel pattern).

Tests: 12 new (60 → 72 total). Mock-based body capture.

No hosted-PR dependency.

Rebased against main 2026-05-04 (post-#28 agents-group merge).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
Drains 3 entries from cueapi-cli #25's `endpoints_missing`:

- POST /v1/executions/{id}/replay → `cueapi executions replay <id>`
- POST /v1/executions/{id}/verification-pending → `cueapi executions verification-pending <id>`
- POST /v1/executions/{id}/verify → `cueapi executions verify <id> [--valid|--invalid] [--reason "..."]`

`verify` is tri-state: `--valid` sends True, `--invalid` sends False,
neither sends empty body (matches server's pre-schema legacy callers).
`--reason` length capped at 500 chars client-side.

Tests: 12 new (60 → 72 total).

No hosted-PR dependency.

Rebased against main 2026-05-04 (post-#28 agents-group merge).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
…(#589 + #590 port)

Cross-package parity port for two pending hosted-API PRs in cueapi/cueapi:

- #589 (executions GET surfaces effective payload): `cueapi executions
  get` now pretty-prints the new `payload` field from the response when
  present (omits when null).
- #590 (per-cue server-side enforcement of payload_override on /fire):
  adds --require-payload-override / --no-require-payload-override and
  --required-keys to `create` and `update` commands.

Click tri-state for require-payload-override (None=omit, True/False=send
explicitly). --required-keys is comma-separated; empty string sends `[]`
(explicit clear).

Tests: 14 new (60 → 74 total). Mock-based body-construction.

Depends on cueapi/cueapi#589 + cueapi/cueapi#590 merging to staging then
prod for user-visible behavior. PR can merge independently — new options
are no-ops against an old server.

Rebased against main 2026-05-04 (post-#28 agents-group merge).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
…-evidence / triggered-by

Closes the cueapi-cli #25 manifest gap on `cueapi executions list`.
Server-side already supports all four filters (`app/routers/executions.py`);
this exposes them in the CLI.

- --outcome-state: reported_success / reported_failure / verified_success /
  verification_pending / verification_failed / unknown
- --result-type: filter by evidence result_type
- --has-evidence: flag — only sent when present (omit-when-default to keep
  URLs clean)
- --triggered-by: scheduled / manual_fire / chain

Tests: 6 new (60 → 66 total).

No hosted-PR dependency — server already supports the filters.

Rebased against main 2026-05-04 (post-#28 agents-group merge).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
…, verification, on-success-fire, status)

Drains create + update command_drift entries. Click Choice validation
on --catch-up + --status. --clear-on-success-fire sends literal null.

Tests: 12 new (60 → 72 total).
No hosted-PR dependency.
Rebased against main 2026-05-04 (post-#28, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
Drains 3 endpoints_missing entries. verify is tri-state (--valid / --invalid / neither).
--reason capped at 500 chars client-side.

Tests: 12 new (71 → 83 total).
No hosted-PR dependency.
Rebased against main 2026-05-04 (post-#28, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
govindkavaturi-art pushed a commit that referenced this pull request May 4, 2026
…, verification, on-success-fire, status) (#30)

Drains create + update command_drift entries. Click Choice validation
on --catch-up + --status. --clear-on-success-fire sends literal null.

Tests: 12 new (60 → 72 total).
No hosted-PR dependency.
Rebased against main 2026-05-04 (post-#28, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
…(#589 + #590 port)

Cross-package parity port for hosted #589 + #590. Click tri-state for
require-payload-override. --required-keys empty string sends [] explicitly.

Tests: 14 new (71 → 85 total).
Depends on cueapi/cueapi#589 + #590 for user-visible behavior; merges
independently.
Rebased against main 2026-05-04 (post-#28, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
…-evidence / triggered-by

Closes cueapi-cli #25 manifest gap on executions list. Server-side already
supports all 4 filters. --has-evidence flag only sent when present.

Tests: 6 new (71 → 77 total).
No hosted-PR dependency.
Rebased against main 2026-05-04 (post-#28, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
…age lifecycle)

Closes messages portion of Messaging primitive endpoints_missing.
4 commands (send/get/read/ack). --from goes in X-Cueapi-From-Agent header.
--idempotency-key max 255 chars enforced client-side.

Tests: 18 new (71 → 89 total).
No hosted-PR dependency.
Rebased against main 2026-05-04 (post-#28, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
…(#589 + #590 port)

Cross-package parity port for hosted #589 + #590. Click tri-state for
require-payload-override. --required-keys empty string sends [] explicitly.

Tests: 14 new (83 → 97 total).
Depends on cueapi/cueapi#589 + #590 for user-visible behavior; merges
independently.
Rebased against main 2026-05-04 (post-#28, #30, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
verify is tri-state (--valid / --invalid / neither). --reason capped at 500 chars.
Tests: 12 new (83 → 95 total).
Rebased against main 2026-05-04 (post-#28, #30, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
govindkavaturi-art pushed a commit that referenced this pull request May 4, 2026
…(#589 + #590 port) (#26)

Cross-package parity port for hosted #589 + #590. Click tri-state for
require-payload-override. --required-keys empty string sends [] explicitly.

Tests: 14 new (83 → 97 total).
Depends on cueapi/cueapi#589 + #590 for user-visible behavior; merges
independently.
Rebased against main 2026-05-04 (post-#28, #30, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
Adds 3 new subcommands to the executions group. verify is tri-state
(--valid / --invalid / neither). --reason capped at 500 chars client-side.

Tests: 12 new (83 → 95 total).
No hosted-PR dependency.
Rebased against main 2026-05-04 (post-#28, #30, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
4 filters: --outcome-state / --result-type / --has-evidence / --triggered-by.
--has-evidence flag only sent when present.

Tests: 6 new (83 → 89 total).
No hosted-PR dependency.
Rebased against main 2026-05-04 (post-#28, #30, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
4 commands (send/get/read/ack). --from goes in X-Cueapi-From-Agent header.
--idempotency-key max 255 chars enforced client-side.

Tests: 18 new (83 → 101 total).
No hosted-PR dependency.
Rebased against main 2026-05-04 (post-#28, #30, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
Same as before: 4 filters, 6 new tests.
Rebased against main 2026-05-04 (post-#26, #28, #30, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
govindkavaturi-art pushed a commit that referenced this pull request May 4, 2026
Same as before: 4 filters, 6 new tests.
Rebased against main 2026-05-04 (post-#26, #28, #30, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
…(rebase v5)

Adds 3 new subcommands. verify is tri-state. --reason capped at 500 chars.

Tests: 12 new (97 → 109 total).
No hosted-PR dependency.
Rebased against main 2026-05-04 (post-#26, #28, #30, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
4 commands. --from in X-Cueapi-From-Agent header. Tests: 18 new (97 → 115 total).
No hosted-PR dependency.
Rebased against main 2026-05-04 (post-#26, #28, #30, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
…(rebase v6)

3 new subcommands. verify tri-state. --reason capped at 500 chars.
Tests: 12 new (109+12=121 total).
Rebased against main 2026-05-04 (post-#26, #27, #28, #30, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
4 commands. Tests: 18 new.
Rebased against main 2026-05-04 (post-#26, #27, #28, #30, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
govindkavaturi-art pushed a commit that referenced this pull request May 4, 2026
…(rebase v6) (#31)

3 new subcommands. verify tri-state. --reason capped at 500 chars.
Tests: 12 new (109+12=121 total).
Rebased against main 2026-05-04 (post-#26, #27, #28, #30, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 4, 2026
4 commands. Tests: 18 new (115 → 133 total).
Rebased against main 2026-05-04 (post-#26, #27, #28, #30, #31, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
govindkavaturi-art pushed a commit that referenced this pull request May 4, 2026
4 commands. Tests: 18 new (115 → 133 total).
Rebased against main 2026-05-04 (post-#26, #27, #28, #30, #31, #33).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.

2 participants