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

# Integrating your agent

> Connect your existing OpenAI, Anthropic, Gemini or Bedrock Python client to dashboard capture and keep each task's calls grouped together.

The current connection uses a source URL from **Data** and explicit request
headers. Your existing provider SDK continues making calls and your application
continues executing tools. OpenAI and Anthropic use the generated helper below;
Gemini and Bedrock are set up [directly in the client](#gemini-and-bedrock).

Use [Set up with your coding agent](/agent-setup) to generate the helper. The CLI
and helper ship in `rbtrace==1.2.1` on PyPI.

## Client construction

The helper supplies the exact source URL and capture authentication header:

```python theme={null}
from openai import OpenAI
import reasonblocks_setup

client = OpenAI(**reasonblocks_setup.client_kwargs())
```

Use `Anthropic` from the `anthropic` package for an Anthropic source.
`AsyncOpenAI` and `AsyncAnthropic` accept the same settings. The returned
dictionary contains `base_url`, `default_headers` with `x-reasonblocks-key`, and
`max_retries=0`. Preserve your existing model, timeout and other application
settings, and merge existing headers without overwriting `x-reasonblocks-key`.

Automatic SDK retries are disabled on purpose. A timeout can leave paid work with
an unknown outcome, because the provider may already have accepted the request;
an SDK that silently retries would repeat it. Reconcile that outcome before
retrying. If your application has its own reconciliation policy, override
`max_retries` explicitly in the returned dictionary rather than adding a retry
loop around the call.

For installed packages, generate the helper inside the importable package and
include its adjacent `.reasonblocks/config.json` in deployment files — see
[Deploy your connected application](/deployment). Follow the
[helper location guide](/agent-setup#choose-an-importable-helper-location) instead
of changing `sys.path`.

## Gemini and Bedrock

Google Gemini and Amazon Bedrock connect the same way: point the SDK at the source
URL from **Data** and send the capture key and task header with each call. Their
SDKs take those settings differently from the OpenAI and Anthropic clients, so the
setup is written out in full. It is the same code **Data** shows for the source.

### Gemini

```python theme={null}
import os
from uuid import uuid4
from google import genai

run_id = str(uuid4())  # reuse for every call in one task
client = genai.Client(
    api_key=os.environ["GEMINI_API_KEY"],
    vertexai=False,  # a Gemini API key; ignore GOOGLE_GENAI_USE_VERTEXAI
    http_options={
        "base_url": "https://api.reasonblocks.com/capture/SOURCE_ID/gemini",
        "headers": {
            "x-reasonblocks-key": os.environ["RB_CAPTURE_KEY"],
            "x-rb-run": run_id,
        },
    },
)
```

`generateContent` and `streamGenerateContent` are captured, streaming included,
along with tool declarations and tool calls. Tool calls carry an id only on
Gemini 3; on earlier models a call is matched to its result by name and order,
which is less certain when one turn calls the same function several times.

### Bedrock

A Bedrock source is issued for one region, and the region is part of its URL.
boto3 has no constructor argument for an extra header, so the capture key and task
header are added to each request with an event hook:

```python theme={null}
import os
from uuid import uuid4
import boto3

run_id = str(uuid4())  # reuse for every call in one task
client = boto3.client(
    "bedrock-runtime",
    region_name="us-east-1",
    endpoint_url="https://api.reasonblocks.com/capture/SOURCE_ID/bedrock/us-east-1",
)

def _reasonblocks(request, **_):
    request.headers.add_header("x-reasonblocks-key", os.environ["RB_CAPTURE_KEY"])
    request.headers.add_header("x-rb-run", run_id)

client.meta.events.register("request-created.bedrock-runtime.*", _reasonblocks)
```

Authenticate with a **Bedrock API key**, which boto3 uses when
`AWS_BEARER_TOKEN_BEDROCK` is set. SigV4 access keys are not supported here — see
[Boundaries](/endpoint-compatibility#boundaries). `InvokeModel`, `Converse` and
`ConverseStream` are captured, including tool use, tool results and usage.

## Run identity and sequence numbers

Importing the generated helper installs run labelling for the process: every model
call your provider client makes carries an `x-rb-run` header (which task the call
belongs to) and an `x-rb-seq` header (this is call number *n* of that task).
The dashboard groups a task's calls by `x-rb-run`; that group is the unit
full-agent training works on, together with `x-rb-snapshot-id` when you supply
one. The sequence number is carried on every call so a task's calls stay in order;
the dashboard does not currently read it and groups solely by `x-rb-run`. Importing the helper sends no requests.
`RBTRACE_DISABLE=1` turns the labelling off without removing the import;
`doctor` reports that condition.

Labelling applies only to allowlisted hosts. The helper adds your configured
capture hostname to the allowlist itself, so ordinary setups need no host
configuration. If you also set `RBTRACE_HOSTS`, a plain hostname such as
`capture.example.com` matches only that exact host; a leading-dot entry such as
`.example.com` matches its subdomains. Use `example.com,.example.com` when you
intentionally need both the domain and its subdomains. `RBTRACE_HOSTS=*` labels
every host.

Whether you must name tasks depends on the process shape:

* **One task per process** (a script that handles one job and exits): nothing to
  do. The helper labels every call with one run ID for the process.
* **Any long-lived or multi-task process** (a queue worker, a web server, a batch
  loop, a thread pool): call `run_headers()` at every task boundary. This is
  required. Without it the helper stamps one process-wide run ID, so every task
  the process handles collapses into a single `x-rb-run` — and for the dashboard,
  one `x-rb-run` is one training task.

Create the headers once at the start of each task:

```python theme={null}
headers = reasonblocks_setup.run_headers()
```

and pass them on every model call in that task:

```python theme={null}
response = client.chat.completions.create(
    model=model,
    messages=messages,
    tools=tools,
    extra_headers=headers,
)
```

For Anthropic, pass `extra_headers=headers` to `client.messages.create(...)`.
Reuse the headers through the whole task, including after tool execution. A new
task gets new headers. Keep them in task-local state for concurrent jobs and
long-lived workers. Pass `run_id=existing_task_id` if your application already
has a suitable ID: 1–128 letters, numbers, underscores, periods, colons or hyphens.
The sequence number is still added automatically, keyed by the run ID you passed.
Header names are case-insensitive; `X-RB-Run` and `x-rb-run` are the same header.

An existing `with rbtrace.client.run():` scope around each complete task also
names the task and can stay in place. Without task headers or scopes, unscoped
calls share one process-wide run.

Keep the full conversation, policy, tool definitions and actual tool results in
each request. Add the returned assistant message and tool results before the next
call, as required by your existing agent loop.

## Snapshots for later training

Ordinary capture needs no snapshot or sandbox. When preparing full-agent
training, connect a test copy of the real tools and data that resets before each
task. Then attach its actual starting snapshot:

```python theme={null}
headers = reasonblocks_setup.run_headers(snapshot_id=starting_snapshot_id)
```

Keep the same snapshot and run IDs throughout the task. The helper does not create
that test state. See [Train your complete agent](/full-agent-training) for the
adapter and evaluator requirements.

## Verify the real application

Run `python -m rbtrace doctor --path . --json` using your application environment
and the directory chosen at initialization. It checks local configuration, the
Python version, SDK availability, whether the selected SDK's HTTP transport can
be labelled, capture-key presence and the task-header contract, all without
network calls. It does not prove authentication or successful capture.

Test the actual launch command from outside the repository directory, and verify
that the deployed helper and config are present. When running a real workflow is
within your intended scope, confirm its records in **Data**. Normal provider fees
apply.

The helper runs inside Python. A framework that launches a JavaScript or native
child process may make its model calls there; the Python helper does not
instrument that process. Integrate at the real request boundary and use the
[current endpoint contract](/endpoint-compatibility).

For an older generated gateway connection, or a generated `1.1.0` connection that
predates automatic labelling, follow
[the migration procedure](/agent-setup#migrate-an-older-generated-connection).
