Skip to content

AnthropicClient sends temperature: null when temperature is unset (400 from API) — and the MCP queue then silently drops every episode #1794

Description

@drcollect

Summary

With the MCP server configured for llm.provider: anthropic and temperature
left unset (the schema default is None), every extraction request fails with
HTTP 400 from the Anthropic API:

Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error',
'message': 'temperature: Input should be a valid number'}}

Because the episode queue catches all exceptions, logs them, and marks the task
done, every add_memory call still returns success — we submitted a
20-document batch that reported "queued for processing" 20 times and landed 0
episodes. Only comparing get_episodes counts against submissions revealed it.

Environment

  • graphiti-core 0.29.2 (also present in current main @ 993e081a)
  • mcp_server from the same checkout (package mcp-server 1.0.2)
  • anthropic SDK 0.111.0, Python 3.10.21, FalkorDB backend
  • Model: claude-haiku-4-5-20251001

Reproduction

  1. config.yaml with llm.provider: anthropic, a valid ANTHROPIC_API_KEY,
    and no temperature key (schema default None).
  2. Call the add_memory MCP tool with any episode.
  3. Tool returns Episode ... queued for processing; the server log shows the
    400 above, three retries, then
    services.queue_service - ERROR - Error processing queued episode ....
  4. get_episodes for the group: the episode never lands.

Sample failing request IDs (2026-08-24): req_011CeMSZvQydGf5GLXqoYTGN,
req_011CeMSZwJouHufv2wPfzPDT, req_011CeMSZy2zEZLgDLdP5N9uL.

Cause

mcp_server/src/config/schema.py defaults temperature to None
("defaults to None for reasoning models"). The factory comment says downstream
clients omit temperature when it is None — the OpenAI clients do, but
AnthropicClient passes it through to messages.create(...) verbatim, and the
API rejects temperature: null.

Suggested fix

In AnthropicClient, omit the temperature parameter when
config.temperature is None (mirroring the OpenAI clients), or use the SDK's
NOT_GIVEN sentinel.

Separately but compounding: consider surfacing per-episode failures somewhere a
caller can see them (e.g. failure counters in get_status, or a failed-episode
list). A queue that converts hard failures into log lines while the tool call
reports success makes this class of bug invisible to MCP clients.

Workaround

Set temperature: 0.0 explicitly in the llm section of config.yaml.

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