Skip to content

Fix operator chat: CLI never sent agentId, breaking th chat + MCP ask_business on every org - #507

Open
brentrager wants to merge 2 commits into
mainfrom
th-operator-agentid
Open

Fix operator chat: CLI never sent agentId, breaking th chat + MCP ask_business on every org#507
brentrager wants to merge 2 commits into
mainfrom
th-operator-agentid

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

th api smooth-operator chat and the MCP ask_business tool both failed before the turn ever started:

Error: smooth-operator turn
Caused by:
    smooth-operator error: VALIDATION_ERROR: missing 'agentId'

This was not a master-org config gap and not one org. Reproduced on four unrelated orgs — Smoo AI (master), Chakra AI Solutions, HeyPage, Smoo AI Marketing — all identical. Every customer using either operator entry point was broken.

Root cause — the caller, not the server, and not a missing default agent

agentId is required by the SEP Request schema, but smooth-operator-server used to fabricate a UUID when the field was absent. th-68897a moved that check to the boundary where it belongs — handle_create_session now rejects absent-or-blank rather than silently minting an id or storing NULL. That server change is correct.

This hand-rolled WS client in smooth_operator_ws.rs was one of the callers relying on the old fabrication, so it began failing the moment the new server rolled out. The dashboard kept working because it always sent one.

There is no "default operator agent" to wire up, and no org config is missing.

Fix

The create frame now carries a fresh uuid — exactly what the working dashboard client sends (agentId: agentSlug ?? crypto.randomUUID() in smooth-operator-chat.tsx).

It picks no agent, and changes no behaviour. It is a correlation id, not an agents.id: copilot-ws — the pod behind smooth-operator.smoo.ai — runs its storage adapter with with_builtin_session_agent(), which ignores the caller's agent id and binds the session to the org's built-in "Smooth Operator" row. That is precisely why the dashboard's random uuid works.

Every other create_conversation_session caller in this repo already sends uuid::Uuid::new_v4()smooth-daemon/src/scheduler.rs, smooth-code/src/client.rs, smooth-bench, smooth-web/operator.ts. This one was the lone straggler; the fix makes it consistent.

One fix covers both reported entry points: th … chat and MCP ask_business both route through operator_turn.

Verification

Built the binary and ran it against production:

  • master org: Reply with exactly: OKOK ✅ (was VALIDATION_ERROR)
  • second org (Chakra): OK
  • resume path: same conversation_id returned, prior turn recalled ✅
  • tools live on the session: "How many deals are in our CRM pipeline right now?""There are 11 deals in your CRM pipeline right now." ✅ — confirms it binds to the org's built-in operator with its full tool set, not an empty agent row

Gates: cargo fmt --check clean; cargo clippy (CI's exact command — the workflow deliberately omits -D warnings so advisory pedantic lints are not weaponized) passes with zero warnings from the changed file; 7/7 tests pass.

Tests + negative controls

Frame construction moved into a pure create_frame so the regression is testable. Each assertion was broken and confirmed to fail:

# Mutation Expected Result
1 remove agentId (the original bug) all 3 fail ✅ 3 failed
2 agentId = " " (blank) nonblank + uuid fail ✅ (see below)
3 agentId = "not-a-uuid" uuid test only ✅ 1 failed, 2 passed
4 constant agentId fresh test only ✅ 1 failed, 2 passed
5 drop conversationId on resume resume test only ✅ 1 failed, 2 passed

Control 2 earned its keep: the resume test passed on a whitespace agentId because it checked is_empty() where the server checks trim().is_empty(). Tightened in the second commit, after which control 2 fails all three as it should.

🤖 Generated with Claude Code

brentrager and others added 2 commits August 24, 2026 22:47
…sion

th api smooth-operator chat and MCP ask_business both failed on every org
with VALIDATION_ERROR: missing 'agentId'. Both route through operator_turn,
so one fix covers both.

agentId is required by the SEP Request schema; smooth-operator-server used to
fabricate one for an absent field, and th-68897a moved that check to the
boundary. This client relied on the fabrication. The dashboard did not, which
is why the UI kept working.

Send a fresh uuid, matching the dashboard's agentSlug ?? crypto.randomUUID().
It is a correlation id, not an agents.id: copilot-ws runs its storage adapter
with with_builtin_session_agent(), which ignores the caller's agent id and
binds the session to the org's built-in Smooth Operator row. No agent is
picked and no behaviour changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The negative control found it: with agentId set to "   " the resume test
still passed, because it checked is_empty() where the server checks
trim().is_empty(). A whitespace agentId would have shipped past that
assertion while still being rejected on the wire.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 26f500a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@smooai/smooth Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

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