Anthropic

Using Anthropic Claude models with Flux — setup, API keys, model selection, streaming, structured output, and reasoning effort.

Flux talks to Anthropic through the anthropic Python SDK. The integration lives in flux/tasks/ai/anthropic.py and exposes Claude models through the same agent() factory as every other provider.

Install

The Anthropic SDK is an optional dependency. Install it directly:

pip install anthropic

Or bring in every supported LLM provider at once with the ai extra on flux-core:

pip install flux-core[ai]

The ai extra pulls ollama, openai, anthropic, and google-genai. There is no per-provider extra in 0.56.0 — either install the SDK directly or take the full bundle.

API key

Anthropic’s SDK reads its credential from the ANTHROPIC_API_KEY environment variable. Flux constructs AsyncAnthropic() with no arguments, so the SDK’s default lookup applies:

export ANTHROPIC_API_KEY="sk-ant-..."

If the variable is missing, the first agent call raises an authentication error from the Anthropic SDK rather than a Flux error.

Model string

Every agent() call takes a model parameter in "provider/model_name" format. For Anthropic, the prefix is anthropic/:

from flux.tasks.ai import agent

assistant = await agent(
    "You are a helpful assistant.",
    model="anthropic/claude-sonnet-4-20250514",
)

The model name is forwarded verbatim to client.messages.create(model=...). Use the model identifiers Anthropic publishes — claude-sonnet-4-20250514, claude-opus-4-20250514, claude-haiku-4-20250514, and earlier 3.x families are all valid. A typo lands as an HTTP 400 from the API, not a Flux registration error.

Streaming

Streaming is on by default. agent() accepts stream: bool = True; the Anthropic formatter uses client.messages.stream() and yields tokens through Flux’s progress() task. Streaming is disabled automatically whenever response_format is set.

assistant = await agent(
    "You are a helpful assistant.",
    model="anthropic/claude-sonnet-4-20250514",
    stream=True,
)

See Streaming responses for the agent-loop details.

max_tokens

Anthropic requires max_tokens on every request. Flux defaults to 4096 and forwards the value as max_tokens to the Messages API. Raise it for long outputs:

assistant = await agent(
    "Write detailed technical reports.",
    model="anthropic/claude-sonnet-4-20250514",
    max_tokens=8192,
)

max_tokens is honored by Anthropic, OpenAI, and Gemini. Ollama governs output length through the model’s num_predict setting instead. See the provider comparison for the full matrix.

Reasoning effort

Claude’s extended-thinking mode is exposed through the reasoning_effort parameter. The Anthropic formatter maps it to two API fields: thinking={"type": "adaptive"} and output_config={"effort": <level>}.

researcher = await agent(
    "You are a careful researcher.",
    model="anthropic/claude-sonnet-4-20250514",
    reasoning_effort="high",
)

Valid values are "low", "medium", "high", or None. The formatter applies both fields whenever reasoning_effort is truthy (see anthropic.py::build_messages). Anthropic also supports reasoning streams: thinking-deltas arrive as separate thinking_delta events and are surfaced through the same agent-loop callbacks as text tokens.

Structured output

Pass a Pydantic BaseModel subclass as response_format and the agent returns an instance of that class:

from pydantic import BaseModel

class Sentiment(BaseModel):
    label: str
    confidence: float

classifier = await agent(
    "Classify the sentiment of the text.",
    model="anthropic/claude-sonnet-4-20250514",
    response_format=Sentiment,
)
result: Sentiment = await classifier("This is great!")

Anthropic structured output is API-enforced. The Messages API has no response_format parameter, so Flux constrains the response shape with a forced tool call: apply_structured_output() registers a synthetic respond_with_structured_output tool whose input_schema is the requested model’s JSON schema, and sets tool_choice to require that tool. The API then guarantees the tool input matches the schema. Flux surfaces the tool input as the final answer text, which the agent loop validates with response_format.model_validate_json().

Because the forced tool call commandeers the tools and tool_choice request fields, structured output is mutually exclusive with caller-supplied tool use; the agent loop only applies it when no tools are configured. Forced tool use is also incompatible with extended thinking, so Flux drops the thinking and output_config fields when structured output is active.

What can go wrong

See also