Metadata-Version: 2.5
Name: actaclad-agentguard
Version: 1.8.0
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: claude-agent-sdk
Requires-Dist: claude-agent-sdk>=0.1.0; extra == 'claude-agent-sdk'
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: langchain>=0.3.0; extra == 'langchain'
Requires-Dist: langgraph>=0.2.0; extra == 'langchain'
Provides-Extra: mcp
Requires-Dist: mcp>=1.0.0; extra == 'mcp'
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.

### Naming your agents

Tell AgentGuard which agent a process or run is, so traces from different
agents in one project can be told apart:

```python
agentguard.init(agent="support-agent")              # every trace from this process
with agentguard.policy(agent="refund-agent"):       # one scope
    ...
with agentguard.start_trace("refund", agent="refund-agent"):  # one run
    ...
```

The closest one wins: the scope or run, then `init()`, then
`AGENTGUARD_AGENT`. The name is recorded on the trace as metadata
`agentguard.agent.key`, as written. AgentGuard derives the agent's key from it
(lowercase, `-` separated, at most 64 characters). Use a stable name. A name
that changes per request, such as one with an id, timestamp or UUID in it, is
ignored, and so is a framework default such as `Agent` or `LangGraph`.

## 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)`.

**Tools are guarded automatically.** LangChain tools (including LangGraph's
`ToolNode`) and CrewAI tools get a permission check, and their arguments and
results are scanned. For MCP, instrument the client session:

```python
from agentguard.mcp import instrument_mcp_client   # pip install "actaclad-agentguard[mcp]"
instrument_mcp_client(session)
```

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, execution limit guard, your custom policies |
| **Output**      | schema validation, hallucination (LLM-as-judge)                                  |

To try a policy before you enforce it, use observe mode (1.7.0+). Every
guardrail runs and records what it finds, but nothing is blocked; the console
shows those findings as WOULD BLOCK. Redaction still applies.

```python
agentguard.init(project_id="...", guardrails="observe")   # "auto" enforces
```

A **kill switch** in the console blocks every model call in the project. The SDK
checks it every 10 seconds, so it works without a redeploy.

Azure, Bedrock and Vertex clients (sync and async) report their real provider:
`azure`, `bedrock` or `vertex`. List those models under the matching provider
in the Allowed Model List.

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_AGENT`                      | The agent this process runs as (see Naming your agents)                    |
| `AGENTGUARD_CAPTURE_CONTENT`            | `true` to record prompts and responses. Default off — PII-safe by default. |
| `AGENTGUARD_KILL_SWITCH_POLLER_ENABLED` | `false` to turn off the 10-second kill-switch check                        |

Other `init()` options: `agent`, `guardrails` (`auto`, `observe` or `off`),
`environment` (a label on traces), `on_block`
(`raise` or `refuse`), `tracing` (`batch` or `realtime`), `streaming`,
`poll_interval` (seconds, default 900), `kill_switch_poll_interval` (seconds,
default 10).

## 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[mcp]"             # MCP tools
```

Guardrails need no extra install.

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

## Notes

- **Where checks run.** PII, prompt injection and toxic content are scored by
  your AgentGuard host, in one call per step; the text is scanned, not stored.
  Budget and rate limits check server-side counters so limits hold across every
  instance of your service. Everything else runs in your process. The block
  decision is always made in your process.
- **If AgentGuard can't be reached**, PII, injection and toxicity checks let
  the call through and log a warning.
- **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.
