# `Jibu`
[🔗](https://github.com/oliverandrich/jibu/blob/v0.2.1/lib/jibu.ex#L1)

A thin client for the Anthropic API, built on Req.

Request bodies are plain maps, sent unchanged.
Jibu has no model list and no parameter schema.
New API fields therefore work without a new release.

    client = Jibu.new(api_key: System.fetch_env!("ANTHROPIC_API_KEY"))

    {:ok, response} =
      Jibu.messages(client, %{
        model: "claude-opus-5-5",
        max_tokens: 1024,
        messages: [%{role: "user", content: "Hello"}]
      })

    Jibu.Response.text(response)

Start with the [Getting started guide](getting-started.md).

# `ask`

```elixir
@spec ask(Req.Request.t(), String.t() | [map()], keyword()) ::
  {:ok, String.t()} | {:error, Jibu.Error.t()}
```

Sends `prompt` as a user message and returns the text of the answer.

`prompt` is a string or a list of content blocks, see `Jibu.Content`.

## Shortcuts

  * `:system` - the system prompt.
  * `:cache` - `true` marks the system prompt for prompt caching.
  * `:effort` - sets `output_config.effort`, for example `:low`.
  * `:messages` - an earlier conversation; `prompt` is appended to it.
  * `:on_text` - a function that receives each piece of text as it streams in.
    The answer then goes through `stream/3`.

Every other keyword becomes a body field unchanged, for example `temperature: 0`.

A refusal and output cut off at `max_tokens` or at the context window are errors.
Use `messages/2` when you need the whole response.

# `count_tokens`

```elixir
@spec count_tokens(Req.Request.t(), map()) :: {:ok, map()} | {:error, Jibu.Error.t()}
```

Counts the input tokens of a Messages API request body. The body is sent unchanged.
The API does not bill this call.

# `extract`

```elixir
@spec extract(Req.Request.t(), String.t() | [map()], map(), keyword()) ::
  {:ok, term()} | {:error, Jibu.Error.t()}
```

Sends `prompt` with `schema` as structured output and returns the decoded JSON.

Takes the shortcuts of `ask/3` except `:on_text`.
See the [structured output guide](structured-output.md).

# `messages`

```elixir
@spec messages(Req.Request.t(), map()) ::
  {:ok, Jibu.Response.t()} | {:error, Jibu.Error.t()}
```

Sends a Messages API request. The body is sent unchanged.

# `new`

```elixir
@spec new(keyword()) :: Req.Request.t()
```

Builds a client as a `Req.Request`.

## Options

  * `:api_key` - defaults to the `ANTHROPIC_API_KEY` environment variable.
  * `:betas` - beta names sent in the `anthropic-beta` header.
  * `:base_url` - defaults to `https://api.anthropic.com`.
  * `:model`, `:max_tokens` - defaults for `messages/2` bodies. `count_tokens/2` takes only the model.
  * `:defaults` - a map of further body defaults, for example `%{temperature: 0}`.

A field set in a request body always wins over its default.

Every other option goes to `Req.merge/2`, for example `:receive_timeout`, `:headers`
or `plug: {Req.Test, MyStub}`. Headers merge by name with the API headers.

Jibu retries transient failures. Pass `retry: false` to turn that off.
The [errors guide](errors.md) lists the rules.

# `stream`

```elixir
@spec stream(Req.Request.t(), map(), (map() -&gt; any())) ::
  {:ok, Jibu.Response.t()} | {:error, Jibu.Error.t()}
```

Sends a Messages API request as a stream and calls `fun` with each event.

Jibu sets `stream: true` and sends the body otherwise unchanged.
`fun` receives every server-sent event as a decoded map, including `ping` and unknown types.
The result is the assembled message as a `Jibu.Response`.

An `error` event returns `{:error, %Jibu.Error{}}` with the partial message in `body`.
Jibu does not retry once events have arrived when `:retry` is a function.
See the [streaming guide](streaming.md).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
