Metadata-Version: 2.4
Name: amai-tari
Version: 0.1.0
Summary: TARI Lens — see what your AI agent actually did. Content-off behavioral tracing + a conduct score, local and private.
Author-email: AMAI Labs <team@amai.net>
License-Expression: Apache-2.0
Project-URL: Homepage, https://amai.net
Project-URL: Documentation, https://amai.net
Keywords: ai-agents,observability,security,mcp,opentelemetry,llm,conduct-score,agent-monitoring
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: System :: Monitoring
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Operating System :: OS Independent
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic>=2.7
Requires-Dist: python-dotenv>=1.0
Requires-Dist: cryptography>=42
Requires-Dist: fastapi>=0.111
Requires-Dist: uvicorn>=0.29
Requires-Dist: opentelemetry-api>=1.24
Requires-Dist: opentelemetry-sdk>=1.24
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Provides-Extra: langgraph
Requires-Dist: langgraph>=0.1; extra == "langgraph"
Requires-Dist: langchain-core>=0.2; extra == "langgraph"
Requires-Dist: langchain-openai>=0.1; extra == "langgraph"
Requires-Dist: openinference-instrumentation-langgraph>=0.1; extra == "langgraph"
Provides-Extra: agentdojo
Requires-Dist: agentdojo>=0.1; extra == "agentdojo"
Requires-Dist: anthropic>=0.28; extra == "agentdojo"
Provides-Extra: crewai
Requires-Dist: crewai>=0.30; extra == "crewai"
Dynamic: license-file

# TARI Lens

**Catch your AI agent getting hijacked or leaking data — without ever reading your data.**

TARI Lens is a local, **content-off** conduct monitor for AI agents. Add three lines, run
your agent, and see a trace of what it actually did — tool by tool — with plain-English
risk callouts, a single conduct score, and, for MCP-connected agents, **attribution of the
likely third-party source** when something goes wrong. It reads only tool and server
*names* and timing — **never your prompts, tool arguments, or model outputs, and nothing
leaves your machine.**

*A **real model, not a script**: we handed a `gpt-4o-mini` coding agent a poisoned tool result,
and it chose — on its own — to follow the injection: read a secret, encode it, post it out. TARI
caught the chain and attributed it, live. Score, trace, and attribution are real engine output,
captured content-off. The tool is a stub we built and the secret is fake — the model's decision
and TARI's capture are not.*

---

## Why this exists (coding agents are bleeding first)

Agents now act on untrusted input — repo contents, web pages, and third-party **MCP**
tools — with real privileges. That's a new, live attack surface, and the hard numbers are
already in:

- **IBM 2025:** 16% of breaches involved attackers using AI — the first population-level figure.
- **Anthropic threat telemetry:** 832 accounts banned for malicious AI use in a year.
- **Copilot — CVE-2025-53773 (CVSS 7.8):** injection hidden in *repository content* flips the
  coding agent into auto-approve "YOLO mode" → remote code execution that can self-propagate.
- **The MCP supply chain:** an estimated ~200,000 exposed MCP instances (per Cloud Security Alliance
  research) — a structural, largely-unpatched surface. A poisoned MCP tool result can induce an agent
  to read secrets and ship them out.

The usual answer — pipe full prompts and tool I/O into a SaaS observability tool — is a
non-starter for an agent touching proprietary code or data: it means handing your most
sensitive content to a third party. **Lens takes the opposite bet: it reads only behavioral
metadata, never content.** That's enough to reconstruct the trace, catch exfiltration
patterns, and point at the inducing source — with *zero* privacy friction. No security
review. No data leaving the box.

## ⭐ MCP supply-chain attribution

The differentiator: when a risk pattern fires (an exfiltration chain, scope drift, a novel
external sink) and a third-party **MCP tool returned immediately upstream**, Lens names the
**possible inducing source**:

> 🔴 **Obfuscated exfiltration chain** — `read_file → base64_encode → post_to_url`
> ⛓ **Possible MCP supply-chain source — look here:** `acme-docs-mcp` · tool `search_internal_docs`
> *Based on call ordering, not the tool's data — review, not an accusation.*

It does this **content-off** — from the *ordering* of calls across the untrusted MCP
boundary, never from the tool's result. **Honesty cuts both ways:** just as Lens refuses to
cry "all clear" when it can't classify a tool, it refuses to *accuse* an MCP server that was
merely adjacent. Attribution always reads *"possible source — look here,"* never *"this
server hijacked you."*

Nobody else offers neutral, content-off MCP supply-chain attribution. It runs on your own
MCP-connected agent, live.

## 60-second quickstart

```bash
pip install amai-tari       # pure-Python, Node-free; the dashboard UI ships pre-built
```

```python
from tari import TARIInstrument

tari = TARIInstrument("my-agent", store="./.tari")     # ① name it, pick a local store
provider, exporter = tari.start_otel_capture()          # ② capture (attach to your OTel tracer)
# ... run your agent ...
tari.score(tari.trajectory_from_exporter(exporter))     # ③ score → writes a content-off run
```

```bash
tari demo                   # see it now on a bundled sample  (alias for `tari dashboard`)
```

With OpenTelemetry auto-instrumentation (LangGraph / CrewAI via `openinference-*`), step ②
is automatic and you never touch span plumbing.

## What you get

- **A trace timeline** — every step in order, with timing and errors, and a clear
  **local-tool vs MCP-tool** badge so you see exactly which third-party tool your agent's
  behavior turned on. The trace is the always-correct hero.
- **Plain-English risk callouts** — exfiltration chains, out-of-scope tool use, reliability
  failures — each tagged to the OWASP-Agentic (ASI) / MITRE-ATLAS threat it proxies, and
  **attributed to the likely MCP source** when one is upstream.
- **A TARI conduct score (300–850)** across five dimensions — with an honest confidence band
  and disclosed caveats.
- **Multi-agent history** — runs grouped and filterable by agent: a fleet, not one agent.

## Privacy: content-off, verified

Lens captures only metadata — operation type, tool name, MCP server *identity*, sink class,
timing, token counts. There are **no fields** for prompts, tool arguments, or model outputs,
so they cannot reach disk even by accident. A parametrized firewall test parses every source
file and fails the build if any content-bearing field name is referenced in logic.

Everything runs locally — a project-local `./.tari/` folder. No account, no upload, no
telemetry.

## Honest by design

This is a trust product, so it errs toward *"I don't know"* over guessing:

- **The raw trace is the hero; classification is best-effort.** Sink-class and MCP-source
  tags are heuristics over names; tools we can't place are shown as **`unclassified`**, never
  a confident wrong guess.
- **Honesty cuts both ways.** A run with unclassified tools never gets a confident
  "all clear"; an MCP server that was merely adjacent is never *accused* — only flagged as a
  *possible* source to review.
- **The score discloses what it can't see** (unobserved dimensions widen the band), and
  caveats travel with every score. It's a behavioral *risk* proxy from documented priors, not
  a prediction of incidents.

## Status

Early and honest. Methodology `behavioral-v1.0-prior` (documented priors, not yet empirically
fit); discriminative power measured on a proxy benchmark, and that caveat rides with every
score. MCP-over-OpenTelemetry conventions are still stabilizing — detection reads a documented
set of identity attributes and is easy to extend. APIs may change before 1.0.
