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

# Use the SDK

> Understand project clients, runs, steps, subruns, metadata, and lessons.

<script src="/assets/sdk-nav.js" />

## The ownership model

The Python SDK exposes two top-level building blocks:

* `SovaraClient` owns project identity and run-scoped helpers.
* `trace` wraps application functions that should appear as steps.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from sovara import SovaraClient, trace

sovara_client = SovaraClient(project_name="support-agent")
```

All run, subrun, logging, lesson, and control operations go through that client.
The project is not inferred from the working directory.

## Top-level runs

Use one top-level run for one user request, conversation turn, eval sample,
batch job, or other execution you want to inspect.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
with sovara_client.run("research-and-answer"):
    answer = run_agent()
```

The SDK registers the run with the exec server when the context opens and
finalizes it when the context exits. The same context works with `with` and
`async with`.

For a durable conversation or workflow, pass an application-owned correlation
ID. Reusing it appends new steps to the same canonical Sovara run.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
with sovara_client.run("support chat", client_run_id=chat_id):
    sovara_client.log_input(message)
    reply = agent.reply(message)
    sovara_client.log_output(reply)
```

Keep prompts, messages, and secrets out of `client_run_id`; use a stable ID such
as a chat, ticket, or job ID.

## Steps and explicit tracing

Inside a run, supported provider and MCP calls become ordered steps with input,
output, latency, status, and error data. `trace` adds the same visibility to
important application work that automatic instrumentation does not capture.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
@trace
def lookup_customer(customer_id: str) -> dict:
    return crm.lookup(customer_id)
```

Place explicit tracing at shared tool or dispatch chokepoints. A trace filled
with miscellaneous helper calls is harder to understand than one that exposes
the agent's decisions and meaningful actions.

## Subruns

Subruns organize child agents, delegated branches, parallel work, and coherent
multi-step phases under the active run.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
with sovara_client.run("finance-eval"):
    with sovara_client.subrun("sample-42"):
        run_one_sample("sample-42")
```

Nested top-level `client.run(...)` calls are ignored with a warning. Use
`client.subrun(...)` when the child work should appear in the run tree.

## Run metadata

Add the user-visible input/output and small scalar metrics from inside a run.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
with sovara_client.run("answer-question"):
    sovara_client.log_input(question)
    answer = agent(question)
    sovara_client.log_output(answer)
    sovara_client.log_metrics(answered=True, latency_budget_ms=2500)
```

Metric values must be booleans, integers, or finite floats. Keep prompts,
responses, lists, dictionaries, and secrets out of metrics.

## Lessons

Automatic lesson injection is project-wide by default for supported model
calls. Narrow retrieval with `lesson_scope` on a run or subrun:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
with sovara_client.run("answer-question", lesson_scope="financebench/"):
    answer = call_model(question)
```

Temporarily replace the active scope inside a smaller block:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
with sovara_client.lesson_scope(["conventions/", "markets/"]):
    answer = call_model(question)
```

Use manual injection only when your application must place the managed lesson
block itself.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
with sovara_client.run("answer-question"):
    lesson_context = sovara_client.inject_lessons(context={"question": question})
    prompt = f"{lesson_context}\n\n{question}" if lesson_context else question
    answer = call_model(prompt)
```

`inject_lessons(...)` returns a prompt-ready string or `""`. Manual injection
suppresses automatic injection for that model call.

## Controls and concurrency

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
with sovara_client.disable_tracing():
    warm_cache_without_recording()

with sovara_client.disable_lesson_injection():
    answer_without_lessons()
```

Async tasks inherit context. Wrap callables submitted to a thread pool with
`sovara_client.with_context(...)`.

For concurrent top-level runs, set `capture_logs=False` to avoid mixing process
stdout/stderr between runs.

## Inspect the result

Run normally, or use the passive wrapper to print the run ID:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
sovara record -- python agent.py
sovara probe <run-id>
```

Use the [API reference](/sdks/python/api-reference) for exact signatures.
