Metadata-Version: 2.4
Name: usegradient
Version: 1.3.1
Summary: Python SDK for the Gradient agent runtime and observability platform
Project-URL: Homepage, https://usegradient.dev
Project-URL: Documentation, https://github.com/use-gradient/gradient/tree/main/sdk/python
Project-URL: Repository, https://github.com/use-gradient/gradient
Project-URL: Issues, https://github.com/use-gradient/gradient/issues
Author: Gradient
License-Expression: MIT
Keywords: agents,gradient,llm,observability,tracing
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.25.0; extra == 'anthropic'
Provides-Extra: openai
Requires-Dist: openai>=1.0.0; extra == 'openai'
Provides-Extra: test
Description-Content-Type: text/markdown

# Gradient Python SDK

Typed, no-dependency Python client for the Gradient console API.

## Install

```bash
pip install usegradient
```

Optional provider extras:

```bash
pip install "usegradient[anthropic,openai]"
```

For local development from this repository:

```bash
pip install -e ./sdk/python
```

## Credentials

The client uses the same credentials file and environment variables as the Go CLI:

- `~/.gradient/credentials`
- `GRADIENT_API_KEY`
- `GRADIENT_API_URL`
- `GRADIENT_REGISTRY_URL`
- `GRADIENT_PROXY_URL`

Environment variables override the credentials file.

## Example

```python
import os

from gradient_sdk import Agent, Environment, Gradient, Model, Trace, tool


@tool
def lookup_policy(topic: str) -> dict[str, str]:
    """Look up an HR policy by topic."""

    policies = {
        "parental_leave": {
            "policy_id": "HR-LEAVE-2026",
            "answer": "Employees receive 16 weeks of paid parental leave.",
        },
        "general": {
            "policy_id": "HR-GENERAL-2026",
            "answer": "Contact HR for general policy questions.",
        },
    }
    return policies.get(topic, policies["general"])


HR_AGENT = Agent(
    Model.CLAUDE_SONNET_5,
    tools=[lookup_policy],
    instructions=(
        "You are a friendly HR assistant. When a question needs policy details, "
        "call lookup_policy with topic 'parental_leave' or 'general' before answering."
    ),
)

if __name__ == "__main__":
    gradient = Gradient(
        project=os.getenv("GRADIENT_PROJECT", "my-first-agent"),
        environment=Environment.python(
            python="3.12",
            packages=["usegradient", "anthropic"],
            env={"ANTHROPIC_API_KEY": os.environ["ANTHROPIC_API_KEY"]},
        ),
    )

    handle = gradient.run(
        HR_AGENT,
        "How much paid parental leave do I receive?",
        trace=Trace.full(),
    )

    print(handle.stdout)
    print(handle.trace_url)
```

The SDK prints progress for credentials, routing, source packaging, project/environment cache resolution, cold start, source upload, dependency cache, remote run, and cleanup.

Use the same object for builds, deployments, and replays:

```python
build = gradient.build()
deployment = gradient.deploy(HR_AGENT, name="hr-policy-agent", trace=Trace.runtime(), scale=1)
report = HR_AGENT.evaluate(
    [{"input": "How much leave?", "expected_output": "HR-LEAVE-2026"}],
    {"mentions_policy": lambda row: row["expected_output"] in row["text"]},
)

print(build.source_hash)
print(deployment.url)
print(report["results"][0]["scores"])
```

For lower-level machine control:

```python
from gradient_sdk import GradientClient, default_machine_template

client = GradientClient.from_credentials()

print(client.whoami())

template = default_machine_template(
    image="registry.usegradient.dev/my-org/my-project@sha256:...",
    project="my-project",
    region="sjc",
)

machine = client.create_machine(template)
client.wait_machine_state(machine.id)
print(machine.id, machine.proxy_url)

client.delete_machine(machine.id)
```

## Publishing

Creating a GitHub release publishes `usegradient` to PyPI via
[`.github/workflows/publish-python-sdk.yml`](../../.github/workflows/publish-python-sdk.yml).
The workflow runs on `release: published`, skips prereleases, syncs the package
version from the release tag (for example `v0.3.0` → `0.3.0`), runs tests,
builds, and uploads the wheel and sdist using the `PYPI_API_TOKEN` repository
secret.

Configure PyPI publishing once:

1. Create the `usegradient` project on [pypi.org](https://pypi.org/) (first release only).
2. Create a PyPI API token with publish access to the `usegradient` project.
3. Add it to the GitHub repository as a `PYPI_API_TOKEN` Actions secret.

## API Coverage

- `Gradient(project=..., environment=...)`
- `Agent(Model.GPT_5_6_LUNA, tools=...)` or `Agent(Model.CLAUDE_HAIKU_4_5, tools=...)`
- `Model.*` exhaustive enum for SDK-supported OpenAI and Anthropic chat/tool models
- `RunContext(project=..., session_id=None, user_id=None, metadata={})`
- `@tool`, `@task`, `@agent.step`
- `agent.run(input)` / `agent.stream(input)` / `agent.deploy(name)` / `agent.evaluate(dataset, evaluators)`
- `Environment.python(...)` / `Environment.node(...)`
- `Trace.off()` / `Trace.semantic()` / `Trace.runtime()` / `Trace.full()`
- `Gradient.build(target=None)`
- `Gradient.run(target, input, trace=Trace.full(), keep=False)`
- `Gradient.deploy(target, name=None, trace=Trace.full(), scale=None)`
- `Gradient.replay(run_id, seed=None, freeze_time=None, egress=None, trace=None)`
- `Gradient.benchmark(target, input, iterations=...)`
- `RunHandle.result()` / `cancel()` / `replay()` / `events()` / `logs()` / `spans()` / `to_dataset()`
- `DeploymentHandle.refresh()` / `start()` / `stop()` / `scale()` / `delete()` / `runs()`
- `BuildHandle.logs()`
- `whoami()`
- `ensure_routable()`
- `list_projects()` / `ensure_project(name)`
- `resolve_environment(project=..., environment=..., source=...)`
- `list_environment_versions(project=None)`
- `create_machine(template)`
- `create_traced_machine(template, trace_mode="full", metadata=None, wait=False)`
- `list_machines()`
- `delete_machine(machine_id)`
- `wait_machine_state(machine_id, state="started")`
- `exec_machine(machine_id, command, stdin=None, timeout_seconds=60, trace=True, watch=None)`
- `list_secrets()`
- `update_secrets(values)` / `set_secret(name, value)` / `unset_secret(name)`
- `create_trace_run(trace_mode="proxy", template=None, metadata=None, capture_policy=None)`
- `attach_trace_run(run_id, machine_id=..., proxy_url=None)`
- `finish_trace_run(run_id)`
- `update_trace_policy(run_id, capture_policy)`
- `delete_trace_run(run_id)`
- `get_trace_run(run_id)`
- `list_trace_runs(limit=50)`
- `list_trace_events(run_id, limit=1000)`
- `list_trace_spans(run_id, kind=None, status=None, query=None)`
- `list_trace_sessions(limit=100, query=None)`
- `list_session_spans(session_id)`
- `trace_metrics(days=30)`
- `query_traces(sql, limit=100)`
- `create_trace_annotation(name=..., value=..., span_id=...)`
- `list_trace_annotations(...)`
- `delete_trace_annotation(annotation_id)`
- `create_dataset(name, description=None)`
- `list_datasets()`
- `get_dataset(dataset_id)`
- `delete_dataset(dataset_id)`
- `add_dataset_example(dataset_id, input=..., expected_output=...)`
- `list_dataset_examples(dataset_id)`
- `delete_dataset_example(dataset_id, example_id)`
- `create_experiment(dataset_id=..., name=...)`
- `list_experiments()`
- `get_experiment(experiment_id)`
- `create_experiment_run(experiment_id, name=...)`
- `record_experiment_results(experiment_id, run_id, results)`
- `update_experiment_run_status(experiment_id, run_id, status)`
- `run_experiment(dataset_id, task=..., evaluators=...)`
- `ingest_trace_event(run_id, ingest_token, event_type=..., data=None)`
- `ingest_trace_events(run_id, ingest_token, events)`
- `trace_template(template, trace)`
- `proxy_url(machine_id, slug=None, proxy_base=None)`
- `default_machine_template(image, project=None, ...)`
