anthropic

    Thin Anthropic Messages API client for MoonBit built on gaato/http and gaato/sdk-runtime.

    anthropic
    llm
    sdk
    messages
    Download zip
    Author
    Version
    0.3.0
    License
    Apache-2.0
    Last updated
    3 days ago
    Downloads
    10

    Dependencies

    #gaato/anthropic

    Unofficial Anthropic Messages API client for MoonBit: buffered and streaming messages, open content blocks and stream events, tool use, on gaato/http and gaato/sdk-runtime. Works against Anthropic-compatible servers through base_url. The caller supplies a Transport and a Clock, for example gaato/http-async.

    Unofficial and experimental. Source, issues and design notes: https://github.com/gaato/mbt-sdk

    Request and response types in gaato/anthropic/gen are generated from the official Python SDK's vendored scripts/mock-spec.json.gz. The selected API surface is Messages (buffered and streaming), token counting, and Models (list and retrieve). Beta APIs, batches, files, and other endpoints are not included. See spec provenance and generation overlays.

    The facade exposes create_message, stream_message, count_tokens, list_models, and retrieve_model. MessageRequest accepts typed input blocks, tool choice, thinking, output configuration, and metadata. Use create_message_params or stream_message_params with generated CreateMessageParams for the wider request vocabulary. Responses retain both the generated message and original raw JSON.

    Migration from 0.1.0's handwritten API:

    • base_url now names the server root because generated paths include /v1. For OpenRouter use https://openrouter.ai/api; remove a trailing /v1 from other compatible server roots.
    • InputContent::Blocks now takes generated InputContentBlock values. Unknown block kinds can be represented with InputContentBlock::Unknown.
    • Stop reasons, usage, and message delta values use generated types. Nullable optional metadata uses gaato/sdk-runtime/json.Presence to distinguish absent, null, and present values.
    • ContentBlock::Thinking now contains both thinking and signature; MessageEvent::MessageDelta contains generated delta and usage values. tool_choice accepts a generated ToolChoice; the tool_choice_auto, tool_choice_any, tool_choice_none, and tool_choice_tool helpers construct common choices.

    The opt-in official API tests cover model listing/retrieval, token counting, buffered/streaming Messages, a tool-result round trip, streamed tool arguments, and buffered/streaming thinking with signatures. Set ANTHROPIC_API_KEY and run scripts/live.sh --filter 'live Anthropic official *' from the repository root. They use Haiku 4.5 with small output limits (thinking requests allow 1,536 output tokens, including a 1,024-token thinking budget). They skip when the key is absent; a skipped run is not evidence of compatibility with the official service.

    CreateMessageParams

    Generated types that the facade uses in its own signatures, re-exported so callers can name them as @anthropic.X. Everything else generated from the spec is reachable through gaato/anthropic/gen.

    InputContentBlock

    Generated types that the facade uses in its own signatures, re-exported so callers can name them as @anthropic.X. Everything else generated from the spec is reachable through gaato/anthropic/gen.

    ListResponseModelInfo

    Generated types that the facade uses in its own signatures, re-exported so callers can name them as @anthropic.X. Everything else generated from the spec is reachable through gaato/anthropic/gen.

    MessageDelta

    Generated types that the facade uses in its own signatures, re-exported so callers can name them as @anthropic.X. Everything else generated from the spec is reachable through gaato/anthropic/gen.

    MessageDeltaUsage

    Generated types that the facade uses in its own signatures, re-exported so callers can name them as @anthropic.X. Everything else generated from the spec is reachable through gaato/anthropic/gen.

    MessageStreamEvent

    Generated types that the facade uses in its own signatures, re-exported so callers can name them as @anthropic.X. Everything else generated from the spec is reachable through gaato/anthropic/gen.

    Metadata

    Generated types that the facade uses in its own signatures, re-exported so callers can name them as @anthropic.X. Everything else generated from the spec is reachable through gaato/anthropic/gen.

    ModelInfo

    Generated types that the facade uses in its own signatures, re-exported so callers can name them as @anthropic.X. Everything else generated from the spec is reachable through gaato/anthropic/gen.

    OutputConfig

    Generated types that the facade uses in its own signatures, re-exported so callers can name them as @anthropic.X. Everything else generated from the spec is reachable through gaato/anthropic/gen.

    StopReason

    Generated types that the facade uses in its own signatures, re-exported so callers can name them as @anthropic.X. Everything else generated from the spec is reachable through gaato/anthropic/gen.

    ThinkingConfigParam

    Generated types that the facade uses in its own signatures, re-exported so callers can name them as @anthropic.X. Everything else generated from the spec is reachable through gaato/anthropic/gen.

    ToolChoice

    Generated types that the facade uses in its own signatures, re-exported so callers can name them as @anthropic.X. Everything else generated from the spec is reachable through gaato/anthropic/gen.

    Usage

    Generated types that the facade uses in its own signatures, re-exported so callers can name them as @anthropic.X. Everything else generated from the spec is reachable through gaato/anthropic/gen.

    Anthropic

    pub struct Anthropic {
    // private fields
    }

    An Anthropic API client backed by the transport-independent SDK runtime.

    Request and response shapes come from the generated gen package, which is produced from the vendored first-party OpenAPI document; this facade adds a small stable vocabulary on top of it.
    impl Debug for Anthropic

    Anthropic::count_tokens

    async fn Anthropic::count_tokens(self : Anthropic, request : MessageRequest) -> Int raise
    SdkError

    Counts the input tokens of a request without creating a message.

    Anthropic::create_message

    async fn Anthropic::create_message(self : Anthropic, request : MessageRequest) -> MessageResponse raise
    SdkError

    Creates and buffers one message.

    Anthropic::create_message_params

    Creates and buffers one message from a generated request, for parameters the facade request does not model. stream is ignored.

    Anthropic::from_client

    fn Anthropic::from_client(client :
    Client
    , version? : String) -> Anthropic

    Wraps a preconfigured runtime client for compatible APIs and tests.

    Anthropic::list_models

    async fn Anthropic::list_models(self : Anthropic, limit? : Int, after_id? : String, before_id? : String) ->
    ListResponseModelInfo
    raise
    SdkError

    Lists one page of models. Follow has_more with after_id=last_id.

    Anthropic::new

    fn Anthropic::new(api_key~ : String, transport : &
    Transport
    , clock : &
    Clock
    , base_url? : String, version? : String, auth_header? : AuthHeader, retry? :
    RetryPolicy
    ) -> Anthropic

    Creates an Anthropic client with the selected authentication header.

    base_url is the server root: generated paths already start with /v1, so an Anthropic-compatible gateway is addressed by its root as well (for example https://openrouter.ai/api).

    Anthropic::retrieve_model

    async fn Anthropic::retrieve_model(self : Anthropic, model_id : String) ->
    ModelInfo
    raise
    SdkError

    Retrieves one model by identifier or alias.

    Anthropic::stream_message

    async fn[E : Error] Anthropic::stream_message(self : Anthropic, request : MessageRequest, f : async (MessageEvent) -> Unit raise E) -> Unit

    Creates a streaming message and dispatches decoded events in arrival order. The stream is read through EOF and closed after success or any failure.

    Anthropic::stream_message_params

    async fn[E : Error] Anthropic::stream_message_params(self : Anthropic, params :
    CreateMessageParams
    , f : async (
    MessageStreamEvent
    ) -> Unit raise E) -> Unit

    Creates a streaming message from a generated request and dispatches the generated events. stream is forced on; ping, error and future event kinds arrive as MessageStreamEvent::Unknown.

    Anthropic::to_repr

    Redacted debug representation of an Anthropic client.

    ApiErrorBody

    pub(all) struct ApiErrorBody {
    type_ : String
    message : String
    } derive(Eq,
    Debug
    )

    The error body returned by the Anthropic API.

    test {
    let error : @anthropic.ApiErrorBody = {
    type_: "invalid_request_error",
    message: "invalid request",
    }
    assert_eq(error.message, "invalid request")
    }

    ApiErrorBody::equal

    Compares API error bodies field by field.

    ApiErrorBody::not_equal

    fn ApiErrorBody::not_equal(x : ApiErrorBody, y : ApiErrorBody) -> Bool

    Compares API error bodies field by field.

    ApiErrorBody::to_repr

    Debug representation of an API error body.

    AuthHeader

    pub(all) enum AuthHeader {
    XApiKey
    Bearer
    } derive(Eq,
    Debug
    )

    Selects the credential header used by the API.

    AuthHeader::equal

    fn AuthHeader::equal(AuthHeader, AuthHeader) -> Bool

    Compares authentication-header choices.

    AuthHeader::not_equal

    fn AuthHeader::not_equal(x : AuthHeader, y : AuthHeader) -> Bool

    Compares authentication-header choices.

    AuthHeader::to_repr

    Debug representation of an authentication-header choice.

    ContentBlock

    pub(all) enum ContentBlock {
    Text(String)
    Thinking(thinking~ : String, signature~ : String)
    RedactedThinking(String)
    ToolUse(id~ : String, name~ : String, input~ : Json)
    Other(String, Json)
    } derive(Eq,
    Debug
    )

    One output content block. Blocks beyond text, thinking and tool use keep their JSON; the typed form is on MessageResponse::message.

    ContentBlock::equal

    Compares output content blocks.

    ContentBlock::not_equal

    fn ContentBlock::not_equal(x : ContentBlock, y : ContentBlock) -> Bool

    Compares output content blocks.

    ContentBlock::to_repr

    Debug representation of an output content block.

    InputContent

    pub(all) enum InputContent {
    Text(String)
    Blocks(Array[
    InputContentBlock
    ])
    } derive(Eq,
    Debug
    )

    Input content as plain text or typed content blocks. A block the generated vocabulary does not know is carried losslessly as @gen.InputContentBlock::Unknown.

    InputContent::equal

    Compares input content, including typed blocks.

    InputContent::not_equal

    fn InputContent::not_equal(x : InputContent, y : InputContent) -> Bool

    Compares input content, including typed blocks.

    InputContent::to_repr

    Debug representation of input content.

    Message

    pub(all) struct Message {
    role : Role
    content : InputContent
    } derive(Eq,
    Debug
    )

    One user or assistant turn sent to the Messages API.

    Message::assistant

    fn Message::assistant(text : String) -> Message

    Creates an assistant message containing plain text.

    test {
    assert_eq(@anthropic.Message::assistant("hello"), {
    role: @anthropic.Assistant,
    content: @anthropic.Text("hello"),
    })
    }

    Message::assistant_blocks

    Creates an assistant message from typed content blocks.

    Message::equal

    fn Message::equal(Message, Message) -> Bool

    Compares messages field by field.

    Message::from_response

    fn Message::from_response(response : MessageResponse) -> Message

    Turns a response into the assistant turn to send back, block for block: text, thinking (with its signature), tool use and every other block the API returned are replayed as input blocks. A block the request vocabulary cannot represent is passed through as raw JSON.

    Message::not_equal

    fn Message::not_equal(x : Message, y : Message) -> Bool

    Compares messages field by field.

    Message::to_repr

    Debug representation of a message.

    Message::tool_result

    fn Message::tool_result(tool_use_id~ : String, content~ : String, is_error? : Bool) -> Message

    Creates a user message containing one tool result block.

    test {
    let message = @anthropic.Message::tool_result(
    tool_use_id="toolu_1",
    content="done",
    )
    assert_eq(message.role, @anthropic.User)
    }

    Message::user

    fn Message::user(text : String) -> Message

    Creates a user message containing plain text.

    test {
    assert_eq(@anthropic.Message::user("hello"), {
    role: @anthropic.User,
    content: @anthropic.Text("hello"),
    })
    }

    Message::user_blocks

    Creates a user message from typed content blocks (images, documents, tool results, ...).

    MessageEvent

    pub(all) enum MessageEvent {
    MessageStart(MessageResponse)
    ContentBlockStart(index~ : Int, block~ : ContentBlock)
    TextDelta(index~ : Int, text~ : String)
    ThinkingDelta(index~ : Int, thinking~ : String)
    SignatureDelta(index~ : Int, signature~ : String)
    InputJsonDelta(index~ : Int, partial_json~ : String)
    ContentBlockStop(index~ : Int)
    MessageDelta(delta~ :
    MessageDelta
    , usage~ :
    MessageDeltaUsage
    )
    MessageStop
    Ping
    Error(ApiErrorBody)
    Other(String, Json)
    } derive(Eq,
    Debug
    )

    One event from a streaming message. Event and delta kinds outside the generated vocabulary retain their raw JSON.

    MessageEvent::equal

    Compares message events, including retained unknown JSON.

    MessageEvent::not_equal

    fn MessageEvent::not_equal(x : MessageEvent, y : MessageEvent) -> Bool

    Compares message events, including retained unknown JSON.

    MessageEvent::to_repr

    Debug representation of a message event.

    MessageRequest

    pub(all) struct MessageRequest {
    model : String
    max_tokens : Int
    messages : Array[Message]
    system : String?
    temperature : Double?
    stop_sequences : Array[String]?
    tools : Array[ToolDef]?
    tool_choice :
    ToolChoice
    ?
    thinking :
    ThinkingConfigParam
    ?
    output_config :
    OutputConfig
    ?
    metadata :
    Metadata
    ?
    extra : Map[String, Json]
    } derive(Eq,
    Debug
    )

    Input accepted by buffered and streaming message creation and by token counting.

    The typed fields cover the common surface; extra is merged into the JSON body after the typed fields and validated against the generated schema, so any other documented parameter (top_p, service_tier, ...) can be passed without a facade change. For full control build a @gen.CreateMessageParams and use Anthropic::create_message_params.

    MessageRequest::equal

    Compares message requests field by field.

    MessageRequest::new

    fn MessageRequest::new(model~ : String, max_tokens~ : Int, messages~ : Array[Message], system? : String, temperature? : Double, stop_sequences? : Array[String], tools? : Array[ToolDef], tool_choice? :
    ToolChoice
    , thinking? :
    ThinkingConfigParam
    , output_config? :
    OutputConfig
    , metadata? :
    Metadata
    , extra? : Map[String, Json]) -> MessageRequest

    Creates a message request and snapshots its mutable inputs.

    test {
    let request = @anthropic.MessageRequest::new(
    model="claude-opus-5",
    max_tokens=64,
    messages=[@anthropic.Message::user("hello")],
    )
    assert_eq(request.messages.length(), 1)
    }

    MessageRequest::not_equal

    fn MessageRequest::not_equal(x : MessageRequest, y : MessageRequest) -> Bool

    Compares message requests field by field.

    MessageRequest::to_count_tokens_params

    The generated token-counting request for this facade request, without extra.

    MessageRequest::to_params

    The generated request for this facade request, without extra. stream selects server-sent events; the facade sets it for stream_message.

    MessageRequest::to_repr

    Debug representation of a message request.

    MessageResponse

    pub(all) struct MessageResponse {
    id : String
    model : String
    role : Role
    content : Array[ContentBlock]
    stop_reason :
    StopReason
    ?
    usage :
    Usage

    message :
    Message

    raw : Json
    } derive(Eq,
    Debug
    )

    A decoded message: the facade view (content), the generated view (message) and the original JSON (raw).

    MessageResponse::equal

    Compares decoded messages field by field.

    MessageResponse::not_equal

    fn MessageResponse::not_equal(x : MessageResponse, y : MessageResponse) -> Bool

    Compares decoded messages field by field.

    MessageResponse::text

    fn MessageResponse::text(self : MessageResponse) -> String

    Concatenates text blocks in response order and ignores other block kinds.

    MessageResponse::to_repr

    Debug representation of a decoded message.

    MessageResponse::tool_uses

    fn MessageResponse::tool_uses(self : MessageResponse) -> Array[(String, String, Json)]

    The tool uses requested by the response, in content order.

    Role

    pub(all) enum Role {
    User
    Assistant
    } derive(Eq,
    Debug
    )

    A participant in a Messages API conversation.

    Role::equal

    fn Role::equal(Role, Role) -> Bool

    Compares message roles.

    Role::not_equal

    fn Role::not_equal(x : Role, y : Role) -> Bool

    Compares message roles.

    Role::to_repr

    Debug representation of a message role.

    ToolDef

    pub(all) struct ToolDef {
    name : String
    description : String?
    input_schema : Json
    strict : Bool?
    } derive(Eq,
    Debug
    )

    A client tool definition for the Messages API.

    test {
    let tool = @anthropic.ToolDef::new(name="lookup", input_schema={
    "type": "object",
    })
    assert_eq(tool.name, "lookup")
    }

    ToolDef::equal

    fn ToolDef::equal(ToolDef, ToolDef) -> Bool

    Compares tool definitions field by field.

    ToolDef::new

    fn ToolDef::new(name~ : String, input_schema~ : Json, description? : String, strict? : Bool) -> ToolDef

    Creates a client tool definition with a JSON Schema input object.

    ToolDef::not_equal

    fn ToolDef::not_equal(x : ToolDef, y : ToolDef) -> Bool

    Compares tool definitions field by field.

    ToolDef::to_repr

    Debug representation of a tool definition.

    ToolUseAccumulator

    pub struct ToolUseAccumulator {
    // private fields
    }

    Reconstructs streamed tool-use inputs by content block index.

    test {
    let tools = @anthropic.ToolUseAccumulator::new()
    tools.feed(
    @anthropic.ContentBlockStart(
    index=0,
    block=@anthropic.ToolUse(id="toolu_1", name="lookup", input={}),
    ),
    )
    tools.feed(@anthropic.InputJsonDelta(index=0, partial_json="{}"))
    tools.feed(@anthropic.ContentBlockStop(index=0))
    assert_eq(tools.finish()[0].2, {})
    }

    ToolUseAccumulator::feed

    fn ToolUseAccumulator::feed(self : ToolUseAccumulator, event : MessageEvent) -> Unit

    Consumes one message event. Invalid partial JSON is retained without raising.

    ToolUseAccumulator::finish

    Returns completed tool uses ordered by block index. Invalid accumulated JSON raises @json.ParseError here rather than from feed.

    ToolUseAccumulator::new

    Creates an empty tool-use accumulator.

    api_error

    Extracts an Anthropic error envelope from an HTTP status failure. Returns None for transport, decode, configuration, and malformed error bodies.

    tool_choice_any

    fn tool_choice_any(disable_parallel_tool_use? : Bool) ->
    ToolChoice

    Requires the model to call some tool.

    tool_choice_auto

    fn tool_choice_auto(disable_parallel_tool_use? : Bool) ->
    ToolChoice

    Lets the model decide whether to call a tool.

    tool_choice_none

    Forbids tool calls.

    tool_choice_tool

    fn tool_choice_tool(name : String, disable_parallel_tool_use? : Bool) ->
    ToolChoice

    Requires the model to call the named tool.