Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

---

Adrian is an open-source, [AARM-aligned](https://aarm.dev) runtime security monitoring and control engine for AI agents. It analyses both agent activity logs (tool calls, actions, outputs) and reasoning traces to detect malicious, misaligned, or out-of-remit behaviour, and optionally intervene in-flight. SDKs are available for Python (LangChain) and TypeScript ([sdk/typescript/README.md](sdk/typescript/README.md)), plus a native [Claude Code plugin](integrations/claude-code/README.md) that secures every tool call from your terminal.
Adrian is an open-source, [AARM-aligned](https://aarm.dev) runtime security monitoring and control engine for AI agents. It analyses both agent activity logs (tool calls, actions, outputs) and reasoning traces to detect malicious, misaligned, or out-of-remit behaviour, and optionally intervene in-flight. SDKs are available for Python ([LangChain](sdk/python/README.md), [Anthropic](sdk/python/ANTHROPIC.md)) and TypeScript ([sdk/typescript/README.md](sdk/typescript/README.md)), plus a native [Claude Code plugin](integrations/claude-code/README.md) that secures every tool call from your terminal.

> **🆕 Claude Code plugin - now live.** Drop Adrian into Claude Code and every tool call is classified in real time, with risky actions blocked or held for your approval right in the terminal. No code changes: install with `/plugin marketplace add secureagentics/Adrian` then `/adrian-init`. Full guide: **[integrations/claude-code/README.md](integrations/claude-code/README.md)**.

Expand Down Expand Up @@ -185,10 +185,10 @@ flowchart TD
<td>
<a href="https://www.langchain.com/"><img height="32" src="https://cdn.simpleicons.org/langchain/1FA383" alt="LangChain"></a>&nbsp;&nbsp;
<a href="https://platform.openai.com/docs/agents"><picture><source media="(prefers-color-scheme: dark)" srcset="assets/logos/openai-dark.svg"><img height="32" src="assets/logos/openai-light.svg" alt="OpenAI Agents SDK"></picture></a>&nbsp;&nbsp;
<a href="https://claude.com/claude-code"><img height="32" src="https://cdn.simpleicons.org/claude/D97757" alt="Claude Code"></a>
<a href="https://claude.com/claude-code"><img height="32" src="https://cdn.simpleicons.org/claude/D97757" alt="Claude Code"></a>&nbsp;&nbsp;
<a href="https://docs.anthropic.com/"><img height="32" src="https://cdn.simpleicons.org/anthropic/D97757" alt="Anthropic SDK"></a>
</td>
<td>
<a href="https://docs.anthropic.com/"><img height="32" src="https://cdn.simpleicons.org/anthropic/D97757" alt="Anthropic Agents SDK"></a>&nbsp;&nbsp;
<a href="https://www.crewai.com/"><img height="32" src="https://cdn.simpleicons.org/crewai/FF5A50" alt="CrewAI"></a>&nbsp;&nbsp;
<a href="https://github.com/openclaw/openclaw"><img height="32" src="https://raw.githubusercontent.com/openclaw/openclaw/main/docs/assets/pixel-lobster.svg" alt="OpenClaw"></a>
</td>
Expand Down
104 changes: 104 additions & 0 deletions sdk/python/ANTHROPIC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Adrian for the Anthropic SDK

Anthropic SDK instrumentation for [Adrian](https://github.com/secureagentics/Adrian) security monitoring. Every `messages.create` and `messages.stream` call is captured as a `PairedEvent` and streamed to your backend. Your call sites stay unchanged.

## Install

```sh
pip install "adrian-sdk[anthropic]"
```

Requires Python 3.12+. The extra pins a supported `anthropic` version. Plain `pip install adrian-sdk` also works, since the instrumentation patches whichever `anthropic` your project already depends on. If the package is absent, Adrian skips Anthropic patching and everything else continues as normal.

## Usage

`init` and `shutdown` bracket your normal Anthropic code:

```python
import asyncio
import os

import adrian
import anthropic


async def main():
adrian.init(api_key="adr_local_...")

# Your Anthropic code runs normally, and every call is captured.
client = anthropic.AsyncAnthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

async with adrian.anthropic_invocation():
response = await client.messages.create(
model="claude-opus-5",
max_tokens=1024,
system="You are a helpful assistant.",
messages=[{"role": "user", "content": "What is 2 + 2?"}],
)
# Thinking blocks can precede the text block, so select by type.
print(next(b.text for b in response.content if b.type == "text"))

adrian.shutdown()


asyncio.run(main())
```

Both `anthropic.Anthropic` and `anthropic.AsyncAnthropic` are instrumented. For synchronous code use `adrian.anthropic_invocation_sync()`. Backend configuration, handlers, and the `PairedEvent` schema are shared with the rest of the SDK and are covered in the [SDK README](README.md).

<sup>Last verified with `anthropic==0.96.0` (2026-08-11).</sup>

## Grouping related calls

An invocation is Adrian's unit of work. A single Anthropic call is not one, so wrap related calls to group them under a shared `invocation_id`:

```python
async with adrian.anthropic_invocation():
first = await client.messages.create(...)
second = await client.messages.create(...) # same invocation_id
```

Calls made outside an invocation are still captured, but carry `invocation_id="no_invocation"` and cannot be correlated with each other.

## Streaming

Text deltas stream through untouched. The event is emitted when the final message is requested:

```python
async with adrian.anthropic_invocation():
async with client.messages.stream(
model="claude-opus-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Count to five."}],
) as stream:
async for text in stream.text_stream:
print(text, end="", flush=True)

message = await stream.get_final_message() # emitted and gated here
```

## Execution modes

The agent profile's execution mode is set in the dashboard and pushed to the SDK in the `LoginAck` frame. In Alert mode the response passes through unchanged. In Block and Human Review modes each `tool_use` block in the response waits on the classifier verdict before the response is returned to your code, so a halted tool call never reaches your execution loop. Halted blocks are rewritten to a text block reading `[BLOCKED by security policy]`, and `stop_reason` is downgraded from `tool_use` to `end_turn` so agentic loops terminate cleanly.

The gate fails closed. If no `LoginAck` arrives within 5s, all tool calls are blocked, and in Block mode a verdict timeout blocks the tool call.

## Manual instrumentation

`init()` patches the Anthropic SDK automatically. To control when that happens:

```python
adrian.init(api_key="adr_local_...", auto_instrument=False)
adrian.patch_anthropic()
```

Patching is idempotent and safe to call more than once.

## Not yet covered

- `client.beta.messages` still being a beta feature is not instrumented
- Reasoning content is not captured. A summarised version is available and will be implemented in a follow-up PR.

## Licence

Apache-2.0
2 changes: 2 additions & 0 deletions sdk/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pip install adrian-sdk

Requires Python 3.12+.

Calling the Anthropic SDK directly rather than through LangChain? See [ANTHROPIC.md](ANTHROPIC.md).

## Quickstart

```python
Expand Down
2 changes: 1 addition & 1 deletion sdk/python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "adrian-sdk"
version = "1.0.3"
version = "1.1.0"
description = "Multi-agent security monitoring SDK for LangChain / LangGraph: paired-event capture, real-time classification, and block mode."
readme = "README.md"
license = {text = "Apache-2.0"}
Expand Down
2 changes: 1 addition & 1 deletion sdk/python/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading