Skip to main content

Signed provenance labels and taint-tracking policy for LLM context windows.

Project description

Tessera

Signed provenance, delegation-aware taint tracking, and schema-enforced dual-LLM execution for agent security meshes.

tests python license status

Tessera is a Python library and sidecar proxy that implements two primitives recent agent security surveys identify as unimplemented in production:

  1. Signed trust labels on context segments, with deterministic taint tracking at the tool-call boundary. A tool call requiring USER trust cannot fire if any segment in the context carries WEB trust, regardless of how convincingly that segment impersonates a user instruction.

  2. Schema-enforced dual-LLM execution. The Worker model is structurally prevented from returning free-form text by a Pydantic validator, closing the convention-based hole in Simon Willison's dual-LLM pattern without requiring a custom interpreter.

Both primitives are documented in papers/two-primitives-for-agent-security-meshes.md.


Why this exists

LLM agents concatenate everything they see into one trust-undifferentiated context: user instructions, scraped web pages, tool outputs, memory entries, retrieved documents. The model has no structural way to tell them apart. That is the root cause of indirect prompt injection, and no amount of system-prompting fixes it.

Existing guardrails are WAFs for LLMs: pattern-matching on strings. Tessera treats this as an identity and data-flow problem, not a filtering problem. Every segment of context carries a cryptographic provenance label. The policy engine evaluates tool calls against the minimum trust level observed in the data that could have influenced them. The dual-LLM quarantine executor structurally isolates untrusted content from the model that emits tool calls.

None of the enforcement happens inside the LLM. It happens in deterministic Python outside the model. That is the only way to get guarantees against a probabilistic system.


The core invariant

allow(tool, ctx) iff required_trust(tool) <= min_{s in ctx.segments} s.trust_level

A tool call may execute only if every segment of context that could have influenced the decision has a trust level at or above the tool's required level. The taint-tracking primitive is the use of min, not max. A single untrusted segment drags the whole context to the floor.

The invariant is enforced in tessera.policy.Policy.evaluate, is deterministic, and is testable without invoking an LLM. See tests/test_policy.py for the proofs.


Architecture

   +--------+    +------------------------+    +-----------+
   | User   |--> | Tessera sidecar        |--> | LLM API   |
   +--------+    |                        |    +-----------+
                 |  - verify label sigs   |
   +--------+    |  - spotlight untrusted |
   | Web    |--> |  - taint-track context |
   +--------+    |  - gate tool calls     |
                 |  - emit security events|
   +--------+    |                        |
   | MCP    |--> +----+-------------------+
   +--------+         |
                      v
            +--------------------+    +------------------+
            | tessera.policy     |    | tessera.events   |
            | taint-tracking     |    | SIEM webhook,    |
            +--------------------+    | OTel span events |
                                      +------------------+

            +-----------------------------+
            | tessera.quarantine          |
            |                             |
            |   PLANNER      WORKER       |
            |   (tools)   (no tools)      |
            |      ^          |           |
            |      |   strict_worker      |
            |      +-- WorkerReport ------+
            +-----------------------------+

Every chunk of text entering the model carries a signed label:

TrustLabel(
    origin="web",           # user | system | tool | memory | web
    principal="alice",      # who the content belongs to
    trust_level=0,          # 0=untrusted, 50=tool, 100=user, 200=system
    nonce="...",            # 128-bit random
    signature="..."         # HMAC-SHA256 or JWT-SVID over content + metadata
)

What's in the box

Module Purpose
tessera.labels Signed TrustLabel, HMAC-SHA256 primitives
tessera.signing HMAC and JWT-based label signing and verification, with clock-skew leeway
tessera.context LabeledSegment, Context, Spotlighting delimiters
tessera.delegation Signed delegation tokens for bounded user-to-agent authority
tessera.provenance Signed context segment envelopes and prompt provenance manifests
tessera.identity Inbound workload identity tokens, proof-of-possession, replay checks
tessera.mtls SPIFFE-aware transport identity extraction from ASGI TLS and trusted XFCC
tessera.policy Taint-tracking policy engine with per-tool trust requirements, CEL rules, MCP RBAC, hierarchical scopes
tessera.policy_backends External deny-only policy backends, including OPA integration and audit metadata
tessera.cel_engine CEL expression engine for deny-only policy refinements (requires [cel])
tessera.approval Human-in-the-loop approval gates with fail-closed webhook delivery
tessera.sessions Encrypted in-memory session store for pending approvals, with TTL expiry
tessera.ir Intermediate representation: compile YAML/dict policy config to live Policy instances
tessera.hooks gRPC extension hooks (PostPolicyEvaluate, PostToolCallGate), deny-only, fail-closed
tessera.xds xDS-compatible resource distribution over HTTP/SSE and gRPC ADS (requires [xds])
tessera.scanners Content-aware injection scoring (directive, intent, heuristic), canary leakage detection, PII entity detection, prompt screening, tool output schema enforcement, tool shadow detection
tessera.risk Irreversibility scoring, salami attack chain detection, adaptive cooldown escalation
tessera.compliance NIST SP 800-53 and CWE enrichment, hash-chain tamper-evident audit log
tessera.ratelimit Per-principal token budget enforcement for denial-of-wallet defense
tessera.quarantine QuarantinedExecutor, strict_worker, safe-by-default WorkerReport
tessera.mcp MCP interceptor that auto-labels tool outputs
tessera.a2a A2A security context carriage and verification helpers
tessera.spire Live SPIRE Workload API adapters for JWT-SVIDs and trust bundles
tessera.registry Org-level external-tool registry, registry-wins-on-inclusion
tessera.events Structured SecurityEvent with stdout, OTel, and webhook sinks
tessera.evidence Signed evidence bundles for audit export and offline verification
tessera.output_monitor Output manipulation defense: detects when model outputs deviate from verified tool results
tessera.delegation_intent Delegation intent verification: ensures delegated tool calls match the stated purpose
tessera.trust_decay Time-based trust decay: segments lose trust as they age, configurable per origin
tessera.plan_verifier Plan verification: validates multi-step agent plans against policy before execution
tessera.side_channels Side-channel mitigations: constant-time comparison, timing jitter, output padding
tessera.claim_provenance Claim provenance tracking: binds model assertions to the tool outputs that produced them
tessera.confidence Confidence scoring for scanner results with model-targeting and tense-aware filtering
tessera.taint Value-level taint tracking wired into the policy evaluator and adapter layer
tessera.telemetry Optional OpenTelemetry spans across proxy, MCP, policy, quarantine
tessera.proxy FastAPI reference proxy with chat and A2A JSON-RPC mediation
tessera.adapters.langchain LangChain callback handler: labels segments, gates tool calls, scans outputs (requires [langchain])
tessera.adapters.mcp_proxy Transparent MCP sidecar proxy: sits between any MCP client and a real MCP server, adding trust labels and policy gates to every tool call (requires [mcp])
tessera.adapters.openai_agents OpenAI Agents SDK hook adapter: policy gate on tool start, output labeling, session risk on end (requires [openai-agents])
tessera.adapters.agentdojo AgentDojo benchmark adapter: policy gates and injection scoring in AgentDojo evaluation pipelines (requires [agentdojo])
tessera.adapters.crewai CrewAI step callback: labels segments, gates tool calls, tracks session risk (requires [crewai])
tessera.adapters.google_adk Google ADK before/after tool callbacks: policy enforcement and output labeling (requires [google-adk])
tessera.adapters.llamaindex LlamaIndex callback handler: tool-call gating and output labeling (requires [llamaindex])
tessera.adapters.haystack Haystack pipeline component: policy gate as a pipeline node (requires [haystack])
tessera.adapters.langgraph LangGraph tool node wrapper: gates tool invocations within graph execution (requires [langgraph])
tessera.adapters.pydantic_ai PydanticAI tool wrapper: policy-enforced tool decorator (requires [pydantic-ai])
tessera.adapters.upstream Ready-to-use UpstreamFn callables: openai_upstream (OpenAI, Mistral, Deepseek, xAI, Qwen, Groq, Ollama, vLLM) and anthropic_upstream (with full schema translation)
tessera.liveness Agent liveness attestation via heartbeat TTL (three-property gate: identity AND authority AND liveness)
tessera.hooks.compatibility Decision-event compatibility matrix for hook authoring validation

Reference deployments:


Defense layers (v0.1.0)

Beyond the two core primitives, Tessera v0.1.0 adds layered defenses that compose with the taint-tracking policy engine:

  • Content analysis scanners. Directive detection, intent classification, and heuristic scoring identify injected instructions in tool outputs and retrieved content. Scanners run in parallel with configurable confidence thresholds, model-targeting checks, and past-tense filters to reduce false positives.
  • Output manipulation defense. The output monitor detects when a model's response contradicts or fabricates data relative to the tool outputs it received, catching post-hoc injection where the model is tricked into misrepresenting verified results.
  • Trust decay. Segments lose trust over time based on configurable per-origin decay curves. A tool output that was trustworthy five minutes ago may not be trustworthy five hours later, and the policy engine reflects this automatically.
  • Plan verification. Multi-step agent plans are validated against the policy before execution begins. The verifier checks that every step in the proposed plan would be permitted given the current context, preventing the agent from committing to a sequence it cannot complete.
  • Side-channel mitigations. Constant-time label comparison, timing jitter on policy evaluation, and output padding defend against adversaries who probe the system by measuring response timing or output length to infer trust decisions.
  • Prompt screening. Inbound prompts are screened for known injection patterns before they enter the context, providing an early-reject path that avoids polluting the taint-tracking state with content that would have been blocked anyway.

Framework adapters

Tessera integrates with ten agent frameworks through drop-in adapters. Each adapter wires policy gates, trust labels, and security events into the framework's native extension points:

LangChain, OpenAI Agents SDK, AgentDojo, MCP (transparent sidecar proxy), CrewAI, Google ADK, LlamaIndex, Haystack, LangGraph, PydanticAI.

See the module table above for per-adapter details and optional dependency groups.


Quickstart

python3.12 -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'
pytest

Offline injection demo:

python examples/injection_blocked.py
python examples/quarantine_demo.py

Labeling a segment with HMAC:

from tessera import make_segment, Origin, TrustLevel, Context, Policy

KEY = b"replace-with-a-real-key"

ctx = Context()
ctx.add(make_segment("email bob about the report",
                     origin=Origin.USER, principal="alice", key=KEY))
ctx.add(make_segment("<html>scraped content</html>",
                     origin=Origin.WEB, principal="alice", key=KEY))

policy = Policy()
policy.require("send_email", TrustLevel.USER)

decision = policy.evaluate(ctx, "send_email")
assert not decision.allowed
print(decision.reason)
# context contains a segment at trust_level=0, below required 100 for tool 'send_email'

Outbound workload identity with a SPIRE JWT-SVID:

from tessera import SpireJWTSource

source = SpireJWTSource(socket_path="unix:///tmp/spire-agent-api/api.sock")
headers = source.identity_headers(audience="spiffe://example.org/ns/proxy/i/abcd")

assert "ASM-Agent-Identity" in headers

Dual-LLM execution with schema enforcement:

from tessera import QuarantinedExecutor, strict_worker, WorkerReport

async def raw_worker(untrusted_ctx):
    # call your Worker LLM, return a dict matching WorkerReport
    ...

worker = strict_worker(WorkerReport, raw_worker)

async def planner(trusted_ctx, report: WorkerReport):
    # planner sees only trusted segments + the validated report
    ...

executor = QuarantinedExecutor(planner=planner, worker=worker)
result = await executor.run(full_context)

Proxy wired to any LLM provider:

from tessera.adapters.upstream import openai_upstream, anthropic_upstream, PROVIDERS
from tessera.proxy import create_app

# OpenAI (or drop in Mistral, Deepseek, xAI, Qwen, Groq, Ollama -- same call)
upstream = openai_upstream(api_key="sk-...", base_url=PROVIDERS["mistral"])

# Anthropic (schema translation is handled automatically)
upstream = anthropic_upstream(api_key="sk-ant-...")

app = create_app(policy=policy, verifier=verifier, upstream=upstream)

Security event emission to a SIEM:

from tessera import register_sink, webhook_sink

register_sink(webhook_sink("https://siem.example.com/tessera"))
# Now every POLICY_DENY and WORKER_SCHEMA_VIOLATION is POSTed as JSON.

Threat model

Tessera defends against indirect prompt injection: an attacker controls some segment of data entering the agent's context window and tries to cause the agent to take a privileged action the delegating user did not authorize.

Tessera does NOT defend against:

  • Direct prompt injection by the authenticated user
  • Model-level attacks (backdoors, data poisoning, weight extraction)
  • Compromise of the underlying tool servers or MCP implementations
  • Supply-chain attacks on model weights, system prompts, or tool manifests
  • Sandbox escape for agent-generated code (use Firecracker or gVisor)
  • Semantic poisoning of the agent's natural-language output to the user

See Section 2 of the paper for the full threat model and explicit out-of-scope list.


Tessera and AgentMesh

Tessera is the primitives library. It provides the building blocks for agent security: signed provenance labels, taint-tracking policy, schema-enforced dual-LLM execution, delegation tokens, workload identity, and supporting infrastructure. It is designed to compose with any agent mesh, not to be one.

AgentMesh is the larger goal: a full agent security mesh for AI workloads, analogous to what Istio and Cilium provide for Kubernetes networking. AgentMesh composes Tessera with production infrastructure (agentgateway, SPIFFE/SPIRE, OPA/Cedar, OpenTelemetry) into a unified security control plane with tiered deployment from solo developer to enterprise scale.

The AgentMesh architecture is proposed in docs/AGENT_SECURITY_MESH_V1_SPEC.md. Tessera is the core library that AgentMesh is built on. The Rust gateway in rust/tessera-gateway/ is a reference implementation for contributing primitives upstream to agentgateway.


Composition with existing mesh infrastructure

Tessera is designed to slot into any agent mesh, not to replace one:

  • Identity: custom label JWTs integrate via JWTSigner and JWKSVerifier, while live SPIRE JWT-SVID retrieval and trust-bundle verification integrate via tessera.identity and tessera.spire
  • Transport identity: the reference proxy can enforce SPIFFE caller identity from the ASGI TLS extension, or from X-Forwarded-Client-Cert when the immediate proxy host is explicitly trusted
  • Policy: the Decision object composes with Cedar or OPA for attribute-based rules (evaluate taint first, attributes second)
  • Data plane: the FastAPI reference proxy now covers chat mediation, signed delegation, signed prompt provenance, discovery, and A2A JSON-RPC ingress. It is still a reference surface meant to be ported into a Rust proxy like agentgateway for production
  • Observability: OTel spans emit across proxy.request, proxy.upstream, policy.evaluate, mcp.tool_call, quarantine.run
  • Sandbox: orthogonal, Tessera operates at the application layer

Status

Experimental. v0.1.0 ships ~18,200 lines of Python across 92 modules, ~15,700 lines of tests (991 passing), and a Rust reference gateway. The invariants are testable and the primitives compose, but the API will change, the ergonomics will change, and the integrations with existing mesh infrastructure are not yet battle-tested at scale.

What is stable:

  • The core invariant and its test coverage
  • The TrustLabel structure (HMAC and JWT-SVID signing modes)
  • The strict_worker contract and the safe-by-default WorkerReport

What is likely to change:

  • The FastAPI proxy shape (production deployments should port primitives into a Rust data plane)
  • The MCP interceptor interface as MCP SEP-1913 lands
  • The SecurityEvent sink API as we integrate with more SIEMs
  • The xDS and hooks gRPC wire format (adding delta-xDS and full ACK/NACK in a later release)

Contributing

Contributions are welcome, particularly:

  • Like-for-like CaMeL latency comparison (microbenchmarks for primitive overhead have landed, head-to-head workload comparison is still open)
  • Contributing Tessera primitives upstream to agentgateway as a middleware plugin
  • MCP SEP-1913 interop once the standard lands
  • Additional framework adapters or improvements to the existing ten (LangChain, OpenAI Agents SDK, AgentDojo, MCP, CrewAI, Google ADK, LlamaIndex, Haystack, LangGraph, PydanticAI)
  • Additional test coverage for edge cases in the taint-tracking invariant

Open an issue with questions, corrections, or proposals. Pull requests should include tests that pin the invariant being added or changed.


License

GNU Affero General Public License v3.0 or later. See LICENSE.

The AGPL ensures that anyone running Tessera or AgentMesh as a network service must make their source code available to users of that service. This closes the SaaS loophole that permits companies to run open-source software as a service without contributing improvements back.

The accompanying paper in papers/ is licensed under CC BY 4.0.


Citation

If you use Tessera or the primitives described in the paper:

Philip, K. (2026). Two Primitives for Agent Security Meshes:
Trust-Labeled Context and Schema-Enforced Dual-LLM Execution.
Draft for discussion. https://github.com/kenithphilip/Tessera

Author

Kenith Philip.

Questions, corrections, and implementation feedback are welcome via GitHub issues once the repository is published publicly.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tessera_mesh-0.1.0.tar.gz (297.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tessera_mesh-0.1.0-py3-none-any.whl (231.0 kB view details)

Uploaded Python 3

File details

Details for the file tessera_mesh-0.1.0.tar.gz.

File metadata

  • Download URL: tessera_mesh-0.1.0.tar.gz
  • Upload date:
  • Size: 297.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for tessera_mesh-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6099081b0020d8fe0d9353895c98b90e0d1f050fa0d0b78c7cccd78c13c3641a
MD5 4062bed418d11e9031c584ca866a3b83
BLAKE2b-256 5f0c3f04816e99fb80b0b30b9f22d31f89a764e25a9600fd38f39ce0ba7bba39

See more details on using hashes here.

File details

Details for the file tessera_mesh-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: tessera_mesh-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 231.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for tessera_mesh-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 22ae7a4198a1ad654fffb8c18016739f2fd422fcf215e0f3e81a6f41e328d178
MD5 bdfb7a68e932ffa267d0467a71b6db35
BLAKE2b-256 4ce0dd7df94939c65dc141f8543fd34871503f3f021001a41f12615b3e24ad04

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page