llm_claude 0.5.0 copy "llm_claude: ^0.5.0" to clipboard
llm_claude: ^0.5.0 copied to clipboard

Anthropic Claude API backend for LLM interactions. Provides streaming chat and tool calling via the Anthropic Messages API.

llm_claude #

pub.flutter-io.cn

Anthropic Claude backend for LLM interactions in Dart. Part of the dart-llm ecosystem.

Available on pub.flutter-io.cn.

Features #

  • Streaming chat responses via the Anthropic Messages API
  • Tool/function calling with automatic multi-turn tool-loop execution
  • Vision (image) support
  • Thinking mode (extended reasoning) support
  • Structured output (JsonSchemaFormat via native output_config.format; JsonFormat via system-message injection)
  • Builder pattern for fluent configuration
  • Configurable retry and timeout policies

Installation #

dependencies:
  llm_claude: ^0.3.2

Prerequisites #

You need an Anthropic API key. Get one from console.anthropic.com.

Important: Never commit your API key to version control. Use environment variables or a .env file.

Usage #

Basic Chat #

import 'package:llm_claude/llm_claude.dart';

final repo = ClaudeChatRepository(apiKey: 'your-api-key');

final stream = repo.streamChat('claude-haiku-4-5-20251001', messages: [
  LLMMessage(role: LLMRole.user, content: 'Hello!'),
]);

await for (final chunk in stream) {
  stdout.write(chunk.message?.content ?? '');
}

System Message #

final stream = repo.streamChat('claude-haiku-4-5-20251001', messages: [
  LLMMessage(role: LLMRole.system, content: 'You are a concise assistant.'),
  LLMMessage(role: LLMRole.user, content: 'Explain quantum entanglement.'),
]);

Tool Calling #

class WeatherTool extends LLMTool {
  @override
  String get name => 'get_weather';

  @override
  String get description => 'Get the current weather for a location.';

  @override
  List<LLMToolParam> get parameters => [
    LLMToolParam(
      name: 'location',
      type: 'string',
      description: 'City name',
      isRequired: true,
    ),
  ];

  @override
  Future<dynamic> execute(Map<String, dynamic> args, {dynamic extra}) async {
    return {'temperature': 22, 'condition': 'sunny'};
  }
}

final stream = repo.streamChat(
  'claude-haiku-4-5-20251001',
  messages: [LLMMessage(role: LLMRole.user, content: 'What is the weather in Oslo?')],
  tools: [WeatherTool()],
);

Structured Output #

Which mechanism is used depends on the format and the model:

Modern & transitional models Legacy models
JsonSchemaFormat native output_config.format with type: json_schema system-message injection
JsonFormat system-message injection system-message injection

There is no native bare-JSON mode in the Anthropic API, so JsonFormat always injects — it appends a JSON instruction after any user-defined system content. Legacy here means Opus/Sonnet 4.5 and earlier, Haiku 4.5 and earlier, and the Claude 3 family; see Models.

import 'package:llm_core/llm_core.dart';

// Simple JSON mode
final stream = repo.streamChat(
  'claude-haiku-4-5-20251001',
  messages: [LLMMessage(role: LLMRole.user, content: 'List three fruits as JSON.')],
  options: const LLMChatOptions(responseFormat: JsonFormat()),
);

// JSON Schema mode
const schema = {
  'type': 'object',
  'properties': {
    'name': {'type': 'string'},
    'age': {'type': 'integer'},
  },
  'required': ['name', 'age'],
};

final stream = repo.streamChat(
  'claude-haiku-4-5-20251001',
  messages: [LLMMessage(role: LLMRole.user, content: 'Return a person object.')],
  options: const LLMChatOptions(
    responseFormat: JsonSchemaFormat(name: 'Person', schema: schema),
  ),
);

Thinking Mode #

Extended reasoning (thinking) is supported on compatible models:

final stream = repo.streamChat(
  'claude-haiku-4-5-20251001',
  messages: [LLMMessage(role: LLMRole.user, content: 'Solve this step by step: ...')],
  think: true,
  options: const LLMChatOptions(
    backendOptions: {
      // haiku-4-5 is a legacy model, so thinking uses a token budget — and the
      // budget is clamped to `max_tokens - 1`. Raise max_tokens alongside it or
      // the effective budget is 4095, not 16000.
      'max_tokens': 24000,
      'thinking_budget': 16000,
    },
  ),
);

await for (final chunk in stream) {
  if (chunk.message?.thinking != null) {
    // Extended reasoning content
    stdout.write(chunk.message!.thinking!);
  } else {
    stdout.write(chunk.message?.content ?? '');
  }
}

Non-Streaming Response #

final response = await repo.chatResponse('claude-haiku-4-5-20251001', messages: [
  LLMMessage(role: LLMRole.user, content: 'Hello!'),
]);

print(response.content);

Using LLMChatOptions #

// `thinking_budget` is only read when `think: true` is set; without it the
// key is dropped.
final options = LLMChatOptions(
  tools: [WeatherTool()],
  toolAttempts: 5,
  backendOptions: {
    'max_tokens': 8192,
    'thinking_budget': 10000,
  },
);

final stream = repo.streamChat('claude-haiku-4-5-20251001', messages: messages, options: options);

Advanced Configuration #

Builder Pattern #

final repo = ClaudeChatRepository.builder()
  .apiKey('your-api-key')
  .baseUrl('https://api.anthropic.com')
  .maxToolAttempts(10)
  .retryConfig(RetryConfig(
    maxAttempts: 3,
    initialDelay: Duration(seconds: 1),
    maxDelay: Duration(seconds: 30),
  ))
  .timeoutConfig(TimeoutConfig(
    connectionTimeout: Duration(seconds: 10),
    readTimeout: Duration(minutes: 5),
  ))
  .build();

Retry Configuration #

final repo = ClaudeChatRepository(
  apiKey: 'your-api-key',
  retryConfig: RetryConfig(
    maxAttempts: 3,
    initialDelay: Duration(seconds: 1),
    maxDelay: Duration(seconds: 30),
    retryableStatusCodes: [429, 500, 502, 503, 504],
  ),
);

Timeout Configuration #

final repo = ClaudeChatRepository(
  apiKey: 'your-api-key',
  timeoutConfig: TimeoutConfig(
    connectionTimeout: Duration(seconds: 10),
    readTimeout: Duration(minutes: 5),
    totalTimeout: Duration(minutes: 10),
  ),
);

Models #

See Anthropic Models for available models:

  • claude-haiku-4-5-20251001 — Low-cost current Haiku model used by live tests
  • claude-opus-5 — Most capable
  • claude-sonnet-5 — Balanced performance and cost
  • claude-haiku-4-5 — Fastest and cheapest

Model families differ in the request shape they accept, and llm_claude selects it automatically from the model id:

Model family Thinking temperature / top_p / top_k Structured output
Opus 4.7+, Sonnet 5, Fable 5, Mythos 5 adaptive rejected (400) — omitted automatically native output_config
Opus 4.6, Sonnet 4.6 adaptive accepted native output_config
Opus 4.5 and earlier, Haiku 4.5, Claude 3 budget_tokens accepted system-prompt injection

Sending budget_tokens to a current model — or a sampling parameter to Opus 4.7+ — is a 400, not a warning. LLMChatOptions.reasoningBudget is translated to an output_config.effort level on models that no longer accept token budgets, so the setting is honored rather than dropped.

On current models an explicit LLMChatOptions.reasoningEffort wins over a budget-derived level (effort-native path); on legacy models the budget wins, and an effort-only request converts through claudeBudgetForEffort (budget-native path).

An unrecognized model id is treated as a current model, so a newly released Claude works without a library update.

Notes #

  • Claude does not support embeddings. embed() and batchEmbed() throw UnsupportedError.
  • JsonSchemaFormat constrains decoding natively via output_config.format on models that support it; JsonFormat always falls back to system-message injection, because the API has no bare-JSON mode.
  • max_tokens defaults to 4096; override via backendOptions['max_tokens'].
  • A thinking budget is clamped to max_tokens - 1 on legacy models. Raise max_tokens alongside thinking_budget or the budget you asked for is not the budget you get.
  • tool_choice accepts the shorthands 'auto', 'any', 'required', 'none' and a bare tool name, in addition to the API's own object form.
  • Retries are off unless you pass a RetryConfig.
0
likes
160
points
330
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Anthropic Claude API backend for LLM interactions. Provides streaming chat and tool calling via the Anthropic Messages API.

Repository (GitHub)
View/report issues
Contributing

Topics

#anthropic #claude #llm #ai #chat

License

MIT (license)

Dependencies

http, llm_core

More

Packages that depend on llm_claude