Skip to main content
Cognis abstracts LLMs behind a single trait — LLMProvider — and bundles concrete clients for the major vendors. Most code touches Client, the provider-agnostic wrapper. Everything below it (request shapes, auth, streaming, tool serialization) is provider-specific and feature-gated.

What it is

Client is Runnable<Vec<Message>, Message> plus a few convenience methods. It wraps an Arc<dyn LLMProvider>, so swapping providers means changing one constructor call, not your chain.

Two ways to construct a Client

Use Client::from_env when env vars decide the provider — by far the most common path. Use provider builders when you need provider-specific knobs (organization id, deployment name, custom headers).

Switching providers

The same agent, six ways. Same code; different env or different provider builder.

What you can do with a Client

How it works

  • Client doesn’t know the provider’s wire format. LLMProvider does. Client packages messages into a generic request and lets the provider serialize.
  • Client is a Runnable. Wrap it with with_max_retries, with_timeout, with_fallback — same as anything else.
  • Tool calls are normalized. Whatever the provider returns (OpenAI’s tool_calls, Anthropic’s tool_use blocks, Gemini’s functionCalls), Cognis flattens to AiMessage.tool_calls: Vec<ToolCall>.
  • Streaming aggregates correctly. A streamed reply that includes a tool call decides — at the chunk level — to enter tool-dispatch mode without breaking the consumer.

Resilience patterns

Models fail. Cognis ships idiomatic recovery wrappers:
For richer policies (cost-based retry, exponential backoff with jitter), see Production → Resilience.

See also

Tools

Give the model something to call.

Streaming

Tokens, events, and structured streams.

Structured output

Get typed structs back from the model.

Reference → cognis-llm

Full provider list and method signatures.