Skip to content

bug(cli): bad --model on spawn (e.g. cursor gpt-5) archives peer silently; wrapper OK is remit-only #1752

Closed as not planned
heavygee/hapi
#140

Description

@heavygee

Symptom

hapi spawn-peer / hapi-spawn-peer with --agent cursor --model gpt-5 creates the session, delivers the remit, prints success — and the agent never runs. The session goes inactive/archived with the remit as the only message and zero agent output.

The wrapper's success check is misleading:

hapi-spawn-peer: OK <sessionId>  name="…"  messages>=1

messages>=1 is true because the remit landed. It does not assert that the agent started or produced output.

Reproduction (operator fleet)

Failed twice (~90 min apart), different session ids, both with --model gpt-5:

hapi-spawn-peer --dir <path> --name "…" \
  --agent cursor --model gpt-5 --session-type worktree --message-file brief.md
hapi-spawn-peer --dir <path> --name "…" \
  --agent cursor --model gpt-5 --session-type simple --message-file brief.md

Control — identical command with --model omitted — succeeds (lifecycle/active running, real agent output).

Isolated variable: --model gpt-5.

Verified on hub after the fact: failed sessions store model: "gpt-5" and active: false; control has model: null and active: true.

Why it is confusing rather than simply wrong

cursor-agent --help documents gpt-5 as an example model string:

--model <model>   Model to use (e.g., gpt-5, sonnet-4-thinking).

But on the same host:

  • cursor-agent --list-models has no bare gpt-5 (current ids look like gpt-5.5, gpt-5.6-sol-high, …)
  • GET /api/machines/:id/cursor-models also has no bare gpt-5 (e.g. gpt-5.5[fast=…], gpt-5.6-sol[fast=…])

So an operator following the CLI help example picks a string the help advertises; spawn accepts any string (SpawnSessionRequestSchema.model is optional unconstrained z.string()), and the runner/agent dies silently — no loud spawn-time error.

Expected

  1. Fail closed at spawn when model is not accepted for the resolved agent flavor (non-zero exit + accepted list). Prefer validating against the flavor's catalog (cursor-models / equivalent), not trusting CLI help examples alone.
  2. Strengthen the spawn-peer success assertion: remit-only messages>=1 is insufficient. Assert agent started / lifecycle running / at least one assistant (or non-user) message before printing OK — or clearly label remit-only as "delivered handoff, agent not verified".
  3. Document accepted model ids per flavor where they diverge from the underlying CLI's --help examples.

(1) is the important fix. A spawn that fails closed and still says OK is worse than one that errors — operators wait on a dead peer.

Related

  • Estate memory / prior bites: bad model param leaves peer silent; overseer must verify — still no product guardrail
  • Empty-shell postmortem (remit missing): different failure mode; this is remit present, agent never runs
  • #1509 / spawn-peer first-class surface — adjacent; does not cover model validation
  • #1427 — Claude DeepSeek / model=auto UI gap — related "bad/default model" family, different flavor

Acceptance

  • --agent cursor --model gpt-5 (or any unknown id) fails at spawn with a clear error listing accepted models (or equivalent catalog check)
  • Known-good catalog ids still spawn and run
  • hapi spawn-peer / wrapper does not print unconditional OK on remit-only when the agent never became active

Activity

  1. added
    bugSomething isn't working
    area:hubHub server (API, sync, store)
    area:cliCLI, runner, agent wrappers
    on Sep 2, 2026
  2. github-actions commented on Sep 2, 2026

    @github-actions

    Confirmed: the core failure mode matches the current spawn implementation.

    An explicit model is accepted as any non-empty string, forwarded unchanged through the hub, and appended to the child CLI arguments. The runner then reports spawn success as soon as the child registers its HAPI session via the local webhook. Cursor ACP initialization and session/new happen after that registration, so a model rejection can occur after the caller already received { type: "success", sessionId }; the Cursor process then follows its crash/archive path.

    The runner already exposes a machine-level Cursor catalog backed by ACP discovery and agent --list-models, so fail-closed validation can use the resolved runner catalog before launching the child. The web Create flow already limits/reset selections against that catalog, but the raw spawn API has no equivalent guard.

    The important readiness fix is also valid: a session-registration webhook proves that the HAPI row exists, not that the underlying agent initialized. Spawn callers should receive a failure, or an explicitly unverified handoff result, until an agent-ready signal is observed.

    One repository mismatch: current main does not register a first-party hapi spawn-peer command, and hapi-spawn-peer is not present in this repository. Therefore I could not verify the exact messages>=1 success string against this checkout. The open #1511 implementation is separate from current main.

    Relevant code:

    • shared/src/apiTypes.ts:610 - spawn request schema accepts model as unconstrained optional z.string()
    • hub/src/web/routes/machines.ts:87 - spawn route parses the request and forwards the model to spawnSession
    • cli/src/runner/run.ts:1562 - runner appends the supplied model directly as --model
    • cli/src/agent/sessionFactory.ts:221 - Cursor creates the HAPI session row before agent initialization
    • cli/src/agent/sessionFactory.ts:234 - session registration is reported to the runner immediately after bootstrap
    • cli/src/runner/run.ts:448 - registration webhook resolves the pending spawn awaiter
    • cli/src/runner/run.ts:881 - webhook resolution becomes a successful spawn result
    • cli/src/cursor/cursorAcpRemoteLauncher.ts:172 - Cursor ACP initialization occurs later
    • cli/src/cursor/cursorAcpRemoteLauncher.ts:307 - fresh native session creation can reject after initialization
    • hub/src/web/routes/machines.ts:362 - machine-level Cursor model catalog endpoint
    • cli/src/modules/common/cursorModels.ts:230 - catalog discovery invokes agent --list-models
    • web/src/components/NewSession/index.tsx:394 - web Create resets a Cursor model missing from the discovered catalog
    • cli/src/commands/registry.ts:41 - current command registry has no spawn-peer entry

    Need more info:

    • What exact hapi --version or commit provides the hapi spawn-peer command in the reproduction?
    • Where is the hapi-spawn-peer wrapper source/version that prints messages>=1?

    HAPI Bot

  3. tiann commented on Sep 14, 2026

    @tiann
    Owner

    Closing pending verification on a current version, as part of the maintainer-requested issue cleanup. This is not a claim that the bug has been fixed or that the existing report is invalid.

    Please update both the HAPI Hub and CLI/runner to the latest release (v0.30.4 at the time of this cleanup), update the relevant Agent CLI, and refresh/update the Web/PWA or native client as applicable. Retest the original steps with the same relevant platform/provider/network configuration.

    If the issue still occurs, please reopen this issue (or comment here to request reopening) with the exact HAPI/Agent/client versions, minimal steps, expected vs. actual result, and fresh sanitized logs or screenshots. If you already reproduced it on that current setup, that confirmation is sufficient to request reopening; we are not asking you to discard existing evidence. Do not include access tokens or credentials.

    Any linked implementation PR is not being closed by this cleanup and can continue independently.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:cliCLI, runner, agent wrappersarea:hubHub server (API, sync, store)bugSomething isn't workingstatus:needs-triageNot yet classified

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions