> ## Documentation Index
> Fetch the complete documentation index at: https://moonshotfactory.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Adapters

> Automatically extract token counts, model names, and cost from LLM API responses.

Adapters read the response object returned by an LLM provider SDK and extract a normalized dict of telemetry fields. You pass that dict directly to `agentvista.record()` or attach it inside an `agentvista.run()` block — no manual token counting required.

Every adapter returns a subset of these fields:

| Field           | Type    | Description                                                                   |
| --------------- | ------- | ----------------------------------------------------------------------------- |
| `model`         | `str`   | Model identifier as returned by the API (e.g. `"claude-sonnet-4-6-20260205"`) |
| `input_tokens`  | `int`   | Input (prompt) token count                                                    |
| `output_tokens` | `int`   | Output (completion) token count                                               |
| `total_tokens`  | `int`   | Sum of input and output tokens                                                |
| `cost_usd`      | `float` | Estimated cost in USD, calculated from known model pricing                    |

Fields present in the response are included; fields that cannot be determined are omitted from the dict.

***

## Anthropic

Install with `pip install agentvista[anthropic]`.

`AnthropicAdapter` works with both sync responses (`client.messages.create(...)`) and streaming responses (`stream.get_final_message()`).

<CodeGroup>
  ```python With record() theme={null}
  import anthropic
  import agentvista
  from agentvista.adapters.anthropic import AnthropicAdapter

  agentvista.init(api_key="av_xxxxx")
  adapter = AnthropicAdapter()

  client = anthropic.Anthropic()
  response = client.messages.create(
      model="claude-sonnet-4-6",
      max_tokens=1024,
      messages=[{"role": "user", "content": "Qualify this lead..."}],
  )

  telemetry = adapter.extract(response)
  # telemetry = {
  #   "model": "claude-sonnet-4-6-20260205",
  #   "input_tokens": 312,
  #   "output_tokens": 87,
  #   "total_tokens": 399,
  #   "cost_usd": 0.002145,
  # }

  agentvista.record(agent="lead-qualifier", success=True, **telemetry)
  ```

  ```python With run() theme={null}
  import anthropic
  import agentvista
  from agentvista.adapters.anthropic import AnthropicAdapter

  agentvista.init(api_key="av_xxxxx")
  adapter = AnthropicAdapter()
  client = anthropic.Anthropic()

  with agentvista.run("lead-qualifier") as r:
      response = client.messages.create(
          model="claude-sonnet-4-6",
          max_tokens=1024,
          messages=[{"role": "user", "content": "Qualify this lead..."}],
      )
      telemetry = adapter.extract(response)

      with agentvista.span("llm-call", span_type="llm"):
          pass  # span timing is captured by run() and span()

      r.set_outcome(success=True, outcome="qualified")
  ```

  ```python Streaming theme={null}
  import anthropic
  import agentvista
  from agentvista.adapters.anthropic import AnthropicAdapter

  agentvista.init(api_key="av_xxxxx")
  adapter = AnthropicAdapter()
  client = anthropic.Anthropic()

  with client.messages.stream(
      model="claude-sonnet-4-6",
      max_tokens=1024,
      messages=[{"role": "user", "content": "Qualify this lead..."}],
  ) as stream:
      for text in stream.text_stream:
          print(text, end="", flush=True)

      # get_final_message() returns the completed Message with usage data
      final = stream.get_final_message()

  telemetry = adapter.extract(final)
  agentvista.record(agent="lead-qualifier", success=True, **telemetry)
  ```
</CodeGroup>

The Anthropic adapter includes cache token counts (`cache_creation_input_tokens` and `cache_read_input_tokens`) in the `input_tokens` total and uses them for accurate cost calculation when prompt caching is active.

***

## OpenAI

Install with `pip install agentvista[openai]`.

`OpenAIAdapter` handles both the **Chat Completions API** (`client.chat.completions.create`) and the **Responses API** (`client.responses.create`). It auto-detects which response shape is present.

<CodeGroup>
  ```python Chat Completions with record() theme={null}
  from openai import OpenAI
  import agentvista
  from agentvista.adapters.openai import OpenAIAdapter

  agentvista.init(api_key="av_xxxxx")
  adapter = OpenAIAdapter()
  client = OpenAI()

  response = client.chat.completions.create(
      model="gpt-4.1",
      messages=[{"role": "user", "content": "Qualify this lead..."}],
  )

  telemetry = adapter.extract(response)
  # telemetry = {
  #   "model": "gpt-4.1",
  #   "input_tokens": 284,
  #   "output_tokens": 93,
  #   "total_tokens": 377,
  #   "cost_usd": 0.001508,
  # }

  agentvista.record(agent="lead-qualifier", success=True, **telemetry)
  ```

  ```python Responses API with run() theme={null}
  from openai import OpenAI
  import agentvista
  from agentvista.adapters.openai import OpenAIAdapter

  agentvista.init(api_key="av_xxxxx")
  adapter = OpenAIAdapter()
  client = OpenAI()

  with agentvista.run("lead-qualifier") as r:
      response = client.responses.create(
          model="gpt-4.1",
          input="Qualify this lead...",
      )
      telemetry = adapter.extract(response)
      r.set_outcome(success=True, outcome="qualified")
  ```
</CodeGroup>

For responses with prompt caching, the adapter reads `cached_tokens` from the usage details object and uses it to compute an accurate cost estimate.

***

## LangChain

Install `langchain-core` in addition to `agentvista`. No extra install extra is required.

`AgentVistaCallbackHandler` is a drop-in LangChain callback handler. Add it to any chain or agent via the `callbacks` argument and spans are produced automatically — no manual `span()` calls needed.

```python theme={null}
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
import agentvista
from agentvista.adapters.langchain import AgentVistaCallbackHandler

agentvista.init(api_key="av_xxxxx")
handler = AgentVistaCallbackHandler(agent_name="lead-qualifier")

llm = ChatOpenAI(model="gpt-4.1")
prompt = ChatPromptTemplate.from_template("Qualify this lead: {lead}")
chain = prompt | llm

# All LLM and chain events are captured automatically
result = chain.invoke({"lead": "Acme Corp, 200 employees"}, config={"callbacks": [handler]})
```

### Span mapping

The handler maps LangChain events to AgentVista span types:

| LangChain event                   | AgentVista span type |
| --------------------------------- | -------------------- |
| `on_chain_start` / `on_chain_end` | `agent`              |
| `on_llm_start` / `on_llm_end`     | `llm`                |
| `on_tool_start` / `on_tool_end`   | `tool`               |

### Combining with `agentvista.run()`

When you add the handler inside an existing `run()` context, its spans become children of that root trace. This lets you attach an outcome signal:

```python theme={null}
with agentvista.run("lead-qualifier") as r:
    result = chain.invoke(
        {"lead": "Acme Corp"},
        config={"callbacks": [handler]},
    )
    qualified = result.content.strip().lower() == "yes"
    r.set_outcome(success=qualified, outcome="qualified" if qualified else "rejected")
```

When used without an enclosing `run()`, the handler auto-creates a trace that is flushed when the outermost chain completes.

<Note>
  If `langchain_core` is not installed, `AgentVistaCallbackHandler` is still
  importable but behaves as a silent no-op. This means you can add the handler
  to shared code without making `langchain_core` a hard dependency for all
  consumers.
</Note>
