Skip to content

Intelligence-mode runs break with strict providers (z.ai GLM / Anthropic): delta-only messages, silent empty replies, LangChain-shaped tool calls in history #199

Description

@MAB2908

Summary

Running a Bot on a strict OpenAI-compatible provider (z.ai GLM, https://api.z.ai/api/coding/paas/v4, model glm-5.3) fails in three related places, all rooted in how intelligence-mode runs and persisted history are handled. OpenAI tolerates all three; GLM (and partly Anthropic) rejects them. Net effect for the user: the agent "stalls" after every browser-executed tool call.

Deployment: openbot v0.0.4 (main @ 6826e11), @copilotkit/runtime 1.68.3, intelligence mode, agents on the managed agent-langgraph runtime.

1. Follow-up runs carry only the message delta — no user turn — and strict providers reject them

In intelligence mode, after the surface executes a frontend tool (e.g. computer_run_command) and starts the next run, the client sends only the new messages:

[ assistant(content: null, toolCalls: […]), tool(result) ]

handleIntelligenceRun fetches thread history only to compute persistedInputMessages (dedup for persistence) — it never merges history into canonicalInput.messages, so the agent receives a conversation with no user message at all.

z.ai rejects this with 400 {"code":1214,"message":"The messages parameter is illegal"}. Verified by direct API bisect: the same payload with any user message added → 200; without → 1214. Anthropic similarly requires the first message to be user.

Suggestion: hydrate canonicalInput.messages from platform history before invoking the agent (the runtime is the only side that owns full history), or document that providers must accept delta-only conversations.

Local workaround we run: agent-langgraph's toLangChainMessages injects a synthetic human "continuation" turn when the converted input contains no human message.

2. An empty model response silently ends the run mid-work

GLM occasionally returns a response with no content and no tool calls. The answer node emits it as-is; the conditional edge sees no tool calls and ends the run. The transcript just stops — no error, no event, the Bot looks dead. Our logs show RUN_STARTEDRUN_FINISHED within ~3 s with zero content events.

Suggestion: treat an empty assistant message as retryable (bounded re-ask) or surface a visible error. Local workaround: in the answer node we re-invoke up to 3 times on an empty reply, then emit a visible fallback message instead of a blank turn.

3. agent-langgraph persists LangChain-shaped tool calls on interrupted runs, which later fails AG-UI validation

When a run is interrupted, persisted history contains tool calls shaped {id, name, args} instead of AG-UI {id, type: "function", function: {name, arguments}}. Consequences on the next run over that thread:

  • server-side run validation rejects the whole run: 400 invalid_literal, expected "function", path: messages.N.toolCalls.0.type — the user cannot send any further message in that thread;
  • the channel transcript renderer crashes reading toolCall.function.arguments (Cannot read properties of undefined).

We found 17 such tool calls in one thread after a couple of interrupted runs.

Suggestion: serialize messages to the AG-UI shape before persistence; consider normalizing on read for existing threads. Local workarounds: a server middleware that rewrites {name, args}{type: "function", function: …} on incoming run bodies, and a normalizing guard in the transcript projection.

Environment

  • openbot v0.0.4, Docker deployment
  • @copilotkit/runtime 1.68.3, intelligence mode (managed CopilotKit Intelligence)
  • Model: z.ai GLM-5.3 via coding endpoint (OpenAI-compatible, BOT_RESPONSES_API=false)
  • The built-in Bots on the same deployment hit the same walls

Happy to provide full request/response captures or test a patch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions