Skip to content

fix(api): message fetch limit exceeds API cap, silencing the subconscious - #52

Open
VooDooDood wants to merge 1 commit into
letta-ai:mainfrom
VooDooDood:fix/message-fetch-limit-exceeds-api-cap
Open

VooDooDood wants to merge 1 commit into
letta-ai:mainfrom
VooDooDood:fix/message-fetch-limit-exceeds-api-cap

Conversation

@VooDooDood

Copy link
Copy Markdown

The subconscious currently cannot deliver any message to Claude Code when running against Letta Cloud. It installs, connects, receives transcripts, and replies normally — but no reply ever reaches the session.

Cause

fetchAssistantMessages in scripts/sync_letta_memory.ts requests limit: 300:

const url = buildLettaApiUrl(`/conversations/${conversationId}/messages`, {
  limit: 300,
});

The API caps limit at 200 and rejects anything larger with HTTP 422:

{"type": "less_than_equal", "loc": ["query", "limit"],
 "msg": "Input should be less than or equal to 200", "input": "300", "ctx": {"le": 200}}

The next branch swallows it:

if (!response.ok) {
  // Don't fail if we can't fetch messages, just return empty
  return { messages: [], lastMessageId: lastSeenMessageId };
}

So every fetch fails, every fetch is silently treated as "nothing new", and the UserPromptSubmit hook emits <!-- No new messages from ... --> on every single prompt.

The failure is invisible from the user side. There is no error, no warning, no degraded mode — the agent simply appears to have nothing to say. Users reasonably conclude the subconscious is uninteresting or broken rather than that delivery is failing.

Reproduce

curl -s -o /dev/null -w "%{http_code}\n" \
  -H "Authorization: Bearer $LETTA_API_KEY" \
  "https://api.letta.com/v1/conversations/<conversation-id>/messages?limit=300"   # 422
  
curl -s -o /dev/null -w "%{http_code}\n" \
  -H "Authorization: Bearer $LETTA_API_KEY" \
  "https://api.letta.com/v1/conversations/<conversation-id>/messages?limit=200"   # 200

Alternatively: run any session, confirm via the API that the agent has produced assistant_message entries, and observe that the hook still reports no new messages.

Origin

Introduced in 8adae7c, which raised the limit from 50 to 300. That change was incidental to the commit it rode in on (fix(windows): eliminate console window flashes using PseudoConsole), which is likely why it escaped review. 04c3423 later refactored the URL construction but preserved the value.

Fix

Lower to 200 — the highest value the API accepts. This preserves the intent of the original bump (reach back past hidden_reasoning/tool entries to the newest assistant_message) while staying inside the cap. A comment is added so the ceiling is not re-raised later.

200 is comfortably sufficient in practice: the hook advances its lastSeenMessageId bookmark on every prompt, so the window only has to span a single turn, and a turn costs a handful of entries. If the bookmark ever did fall outside the window, findIndex returns -1 and the code re-delivers rather than dropping — so the degradation is duplication, not silence.

Scope

Verified against Letta Cloud (api.letta.com), where whisper delivery was restored on the first poll after the change. Self-hosted servers are likely affected identically — the rejection is a Pydantic validation error from the route definition rather than cloud-side configuration — but I have not tested a self-hosted instance directly.

🤖 Generated with Claude Code

…ious

`fetchAssistantMessages` requests `limit=300` from
`GET /v1/conversations/{id}/messages`. The API caps `limit` at 200 and
rejects larger values with HTTP 422:

    {"type": "less_than_equal", "loc": ["query", "limit"],
     "msg": "Input should be less than or equal to 200", "ctx": {"le": 200}}

The `!response.ok` branch treats any failure as "no messages" and returns
an empty array, so the UserPromptSubmit hook emits
`<!-- No new messages from ... -->` on every prompt.

The effect is that the subconscious can never speak. The agent receives
transcripts and replies normally — the replies are visible in the
conversation via the API — but no reply ever reaches Claude Code. It reads
as an agent that has nothing to say rather than as a failure.

Introduced in 8adae7c, which raised the limit from 50 to 300 as an
incidental change inside an unrelated Windows console fix.

Lowering to 200 keeps the intent of the original bump (reach past
reasoning/tool entries to the newest assistant message) at the highest
value the API accepts. Verified against Letta Cloud: whisper delivery
restored on the first poll.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 31, 2026 13:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a Letta Cloud API incompatibility that prevented the subconscious from delivering assistant messages by reducing the message fetch limit to the API’s maximum accepted value, avoiding an HTTP 422 that was previously swallowed and interpreted as “no new messages.”

Changes:

  • Reduce Letta messages fetch limit from 300 to 200 to stay within the API cap.
  • Add an inline note documenting the 200 hard ceiling and why exceeding it causes silent failure.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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