Metadata-Version: 2.4
Name: actaclad-agentguard
Version: 1.5.2
Summary: Agent Guard observability SDK for Python
License-Expression: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Requires-Python: >=3.8
Requires-Dist: httpx>=0.28.0
Requires-Dist: langfuse<5.0.0,>=2.0.0
Requires-Dist: litellm>=1.75.0
Requires-Dist: opentelemetry-api>=1.35.0
Requires-Dist: opentelemetry-exporter-otlp
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.20.0
Requires-Dist: opentelemetry-sdk>=1.20.0
Provides-Extra: all
Requires-Dist: anthropic>=0.20.0; extra == 'all'
Requires-Dist: google-genai>=1.0.0; extra == 'all'
Requires-Dist: llm-guard>=0.3; extra == 'all'
Requires-Dist: numpy<2; extra == 'all'
Requires-Dist: openai>=1.0.0; extra == 'all'
Requires-Dist: opentelemetry-instrumentation-openai; extra == 'all'
Requires-Dist: optimum[onnxruntime]>=1.17; extra == 'all'
Requires-Dist: presidio-analyzer; extra == 'all'
Requires-Dist: presidio-anonymizer; extra == 'all'
Provides-Extra: all-providers
Requires-Dist: anthropic>=0.20.0; extra == 'all-providers'
Requires-Dist: google-genai>=1.0.0; extra == 'all-providers'
Requires-Dist: openai>=1.0.0; extra == 'all-providers'
Requires-Dist: opentelemetry-instrumentation-openai; extra == 'all-providers'
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.20.0; extra == 'anthropic'
Provides-Extra: auto
Requires-Dist: traceloop-sdk>=0.33.0; (python_version >= '3.10') and extra == 'auto'
Provides-Extra: crewai
Requires-Dist: crewai>=0.141.0; extra == 'crewai'
Requires-Dist: openinference-instrumentation-crewai>=0.1.10; extra == 'crewai'
Provides-Extra: gemini
Requires-Dist: google-genai>=1.0.0; extra == 'gemini'
Provides-Extra: guardrails
Requires-Dist: llm-guard>=0.3; extra == 'guardrails'
Requires-Dist: numpy<2; extra == 'guardrails'
Requires-Dist: optimum[onnxruntime]>=1.17; extra == 'guardrails'
Requires-Dist: presidio-analyzer; extra == 'guardrails'
Requires-Dist: presidio-anonymizer; extra == 'guardrails'
Provides-Extra: guardrails-llm
Requires-Dist: llm-guard>=0.3; extra == 'guardrails-llm'
Requires-Dist: numpy<2; extra == 'guardrails-llm'
Requires-Dist: optimum[onnxruntime]>=1.17; extra == 'guardrails-llm'
Provides-Extra: guardrails-pii
Requires-Dist: presidio-analyzer; extra == 'guardrails-pii'
Requires-Dist: presidio-anonymizer; extra == 'guardrails-pii'
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.2.0; extra == 'langchain'
Requires-Dist: langchain-openai>=0.1.0; extra == 'langchain'
Requires-Dist: langgraph>=0.2.0; extra == 'langchain'
Provides-Extra: openai
Requires-Dist: openai>=1.0.0; extra == 'openai'
Requires-Dist: opentelemetry-instrumentation-openai; extra == 'openai'
Provides-Extra: openai-agents
Requires-Dist: nest-asyncio>=1.6.0; extra == 'openai-agents'
Requires-Dist: openai-agents>=0.1.0; extra == 'openai-agents'
Requires-Dist: openinference-instrumentation-openai-agents>=0.1.0; extra == 'openai-agents'
Description-Content-Type: text/markdown

# AgentGuard — Python SDK

Runtime guardrails and observability for LLM and agent applications.

One call to `init()` instruments your provider clients. Every LLM call is then
scanned against the guardrails you configure in the AgentGuard console, and
traced — prompts, responses, token usage, cost, and any guardrail that fired.

```bash
pip install actaclad-agentguard
```

```python
import agentguard

agentguard.init(
    public_key="pk-...",
    secret_key="sk-...",
    base_url="https://your-agentguard-host",
    project_id="your-project-id",
)
```

That is the whole setup. Your existing OpenAI, Anthropic, Gemini or LiteLLM
calls are now guarded and traced — no call sites change.

## Scoping a request

`policy()` attaches identity to the work inside it and opens the trace, so an
agent run is one trace rather than a scatter of unlinked calls.

```python
with agentguard.policy(
    user_id="u-123",
    session_id="s-456",
    feature="support-triage",
    metadata={"tenant": "acme"},
):
    answer = my_agent.invoke(question)
```

Everything inside — guarded LLM calls, tool calls, agent steps — lands in one
trace, with the identity recorded once at the top and filterable in the console.

## Agent frameworks

**LangChain and LangGraph are traced automatically** inside a `policy()` scope.
No callback wiring:

```python
with agentguard.policy(user_id=user_id, feature="triage"):
    agent.invoke({"messages": [{"role": "user", "content": question}]})
```

Pass the handler yourself only if you want to — `agentguard.langchain_handler()`.
Opt out with `policy(autotrace=False)`.

Other frameworks:

```python
agentguard.instrument_crewai()          # pip install "actaclad-agentguard[crewai]"
agentguard.instrument_openai_agents()   # pip install "actaclad-agentguard[openai-agents]"
```

## Guardrails

Guardrails are configured server-side per project and enforced in the SDK, so a
policy change takes effect without a redeploy.

| | |
| --- | --- |
| **Content** | PII redaction, secret scanner, token scanner |
| **Safety** | prompt injection, toxic content |
| **Cost & rate** | budget guard, rate limit, token limit |
| **Policy** | allowed-model list, tool permission |
| **Output** | schema validation, hallucination (LLM-as-judge) |

A blocked call raises, so you can handle it explicitly:

```python
try:
    with agentguard.policy(user_id=user_id, on_block="raise"):
        answer = my_agent.invoke(question)
except agentguard.AgentGuardBlocked as blocked:
    answer = "Sorry — I can't help with that."
```

Use `on_block="refuse"` to get a safe refusal response instead of an exception.

## Configuration

Credentials can come from the environment instead of `init()` arguments:

| Variable | Purpose |
| --- | --- |
| `AGENTGUARD_PUBLIC_KEY` | Project public key |
| `AGENTGUARD_SECRET_KEY` | Project secret key |
| `AGENTGUARD_BASE_URL` | Your AgentGuard host |
| `AGENTGUARD_PROJECT_ID` | Project id |
| `AGENTGUARD_CAPTURE_CONTENT` | `true` to record prompts and responses. Default off — PII-safe by default. |

Other `init()` options: `environment`, `on_block`, `tracing` (`batch` or
`realtime`), `streaming`, `fail`, `poll_interval`.

## API

| | |
| --- | --- |
| `init(...)` | Instrument providers and start guardrail config polling |
| `policy(...)` | Scope guardrails and identity to a block of work; opens the trace |
| `start_trace(name, ...)` | Open a trace explicitly, e.g. to name it |
| `chat(...)` / `achat(...)` | Guarded chat completion through the built-in client |
| `langchain_handler()` | LangChain/LangGraph handler, for passing explicitly |
| `flush()` | Flush pending telemetry — call before a short-lived process exits |
| `AgentGuardBlocked` | Raised when a guardrail blocks a call |

## Optional extras

```bash
pip install "actaclad-agentguard[gemini]"          # google-genai
pip install "actaclad-agentguard[anthropic]"
pip install "actaclad-agentguard[langchain]"       # LangChain / LangGraph
pip install "actaclad-agentguard[guardrails]"      # ML detectors (PII NER, injection, toxicity)
```

The base install keeps dependencies small; each extra is pulled in only when you
need it.

## Notes

- **Enforcement runs in your process.** Detection and the block decision happen
  locally, so a guarded call adds no network hop for most guardrails. Budget and
  rate limits are the exception — they check server-side counters so limits hold
  across every instance of your service.
- **Content capture is off by default.** Prompts and responses are only recorded
  when `AGENTGUARD_CAPTURE_CONTENT=true`.
- **Failures degrade, they don't break.** If telemetry or config polling fails,
  your application call still runs.

---

© ActaClad Technologies. See the AgentGuard console for documentation and
project settings.
