Catalog PyPI
PACKAGE EXPLORERView in registry

ag-ui-claude-sdk-fiqros

PyPI

AG-UI integration for the Anthropic Claude Agent SDK, with multimodal attachment support (images and documents)

Versions collected1
Direct dependencies6From release 0.1.7
Last observed21 Oct, 09:32 UTC

README

Version 0.1.7 documentation

ag-ui-claude-sdk-fiqros

Implementation of the AG-UI protocol for the Anthropic Claude Agent SDK (Python), with support for user attachments — images and documents sent by the user now reach the model instead of being silently discarded.

This is a fork of integrations/claude-agent-sdk from the AG-UI project (MIT), maintained by the Fiqros team. It tracks upstream and adds the attachment fix described in Attachment support below, contributed by the Fiqros team. The import name is unchanged, so it is a drop-in replacement for the upstream package.

Installation

pip install ag-ui-claude-sdk-fiqros

Or from a checkout:

pip install -e .

Usage

The adapter manages the SDK lifecycle internally — just call adapter.run(input_data):

from ag_ui_claude_sdk import ClaudeAgentAdapter, add_claude_fastapi_endpoint

adapter = ClaudeAgentAdapter(name="my_agent", options={"model": "claude-haiku-4-5"})
add_claude_fastapi_endpoint(app=app, adapter=adapter, path="/my_agent")

Attachment support (fork changes)

Investigated, fixed and documented by the Fiqros team.

Upstream, a user message carrying an attachment never reached the model. Claude would reply "It looks like you forgot to attach the image!" — with no error and nothing in the logs.

Cause. When a user attaches a file, AG-UI sends the message content as a list of blocks rather than a plain string:

{"role": "user", "content": [
  {"type": "text",  "text": "what is in this image?"},
  {"type": "image", "source": {"type": "data", "value": "<base64>", "mime_type": "image/png"}}
]}

process_messages() walked that list looking for the first block with a .text attribute, took it, and stopped. Image, document, audio and video blocks have a .source rather than .text, so they matched nothing and fell out of the loop unreferenced. Claude was asked about an image it was never shown.

Fix. AG-UI and Anthropic describe attachments with the same structure under different field names, so the fix is a rename, not a conversion — the base64 payload is passed through untouched, with no decode/re-encode:

AG-UI      {"type": "data",   "value": "<b64>", "mime_type":  "image/png"}
Anthropic  {"type": "base64", "data":  "<b64>", "media_type": "image/png"}

Two changes implement it:

  • utils.py — convert_content_blocks() renames every block and returns the full list. Messages with no attachment still return a plain string, so the common path is byte-for-byte unchanged.
  • session.py — content blocks require ClaudeSDKClient.query()'s streaming form (AsyncIterable[dict]), since its str form cannot carry them. A small async generator wraps the blocks in a user-message envelope.

Also fixed along the way:

  • An attachment-only message (no text) previously produced an empty prompt.
  • A message split into several text blocks lost everything after the first.
  • Unsupported or malformed blocks are now skipped with a warning instead of in silence.

Supported: images and documents, both inline base64 and URL sources. Audio and video blocks are skipped with a warning — Claude does not accept them.

Test coverage

44 tests cover the attachment path (suite total: 110 → 154, with every pre-existing test passing unmodified):

SuiteTestsCovers
TestConvertContentBlocks13Image and document renaming, URL sources, text-only fast path, attachment-only messages, malformed and unknown blocks, base64 passthrough, pydantic models
TestDocumentBlocks15MIME passthrough across 6 document types, multiple documents, mixed image+document, large PDFs, missing MIME
TestProcessMessagesWithAttachments6Block-list vs plain-string return, camelCase mimeType from TypeScript clients
TestAttachmentReachesTheClient5Envelope shape and payload integrity through the real SessionWorker
TestDocumentDelivery5Document delivery, 20 KB PDF unmangled, ordering

The delivery suites run the real SessionWorker with only ClaudeSDKClient substituted, so they assert on exactly what would reach the CLI. Both halves of the fix were also mutation-tested — reverting them fails 7 and 17 tests respectively.

uv run --group dev python -m pytest tests/ -q

Full analysis, evidence and rejected alternatives: BUG_REPORT_attachments_dropped.md.

Features

  • User attachments - Images and documents in user messages are passed through to the model
  • Full lifecycle management - Handles client pooling, message extraction, and event translation internally
  • Interrupt support - Call adapter.interrupt() to stop a running query
  • Dynamic frontend tools - Client-provided tools automatically added as MCP server with auto-granted permissions
  • Frontend tool halting - Streams pause after frontend tool calls for client-side execution (human-in-the-loop)
  • Streaming tool arguments - Real-time TOOL_CALL_ARGS emission as JSON arguments stream in
  • Bidirectional state sync - Shared state management via ag_ui_update_state tool
  • Context injection - Context and state injected into prompts for agent awareness
  • Event cleanup - Hanging events (tool calls, reasoning blocks) automatically closed on stream end
  • Custom tools via MCP - Define custom tools using Claude SDK's @tool decorator
  • Forwarded props - Per-run option overrides with security whitelist

Examples

The integration includes 5 example agents:

RouteDescriptionFeatures
/agentic_chatBasic conversational assistantSimple chat
/backend_tool_renderingWeather tool (backend MCP)Backend tool execution, tool rendering
/shared_stateRecipe collaborationBidirectional state sync, ag_ui_update_state
/human_in_the_loopTask planning with approvalFrontend tools, step tracking, approval workflow
/tool_based_generative_uiFrontend tool renderingDynamic frontend tools, generative UI

Running the Examples

# Install dependencies
cd integrations/claude-agent-sdk/python
pip install -e .

# Start server (port 8019)
cd examples
ANTHROPIC_API_KEY=sk-ant-xxx python server.py

# Start Dojo (in another terminal)
cd apps/dojo
pnpm dev

Visit http://localhost:3000 and select "Claude Agent SDK (Python)"

Session Persistence

Claude SDK maintains conversation state in the .claude/ directory. For production deployments:

  • Development: Sessions persist locally in .claude/{session_id}/
  • Production: Mount .claude/ as a persistent volume in your container
  • Resumption: Pass resume=<session_id> via the options dict or forwarded_props

See Claude SDK Hosting Guide for deployment patterns.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.731 Jul 20266

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Metadata history

Meaningful changes
Current collected state Current

Observed since 21 Oct, 09:32 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:d22eab817a99cf5fbfb59ec427b8297973862a46a2a3c7221caf91c0be0ecd45