Skip to main content

vorim

Official Python SDK for Vorim AI — the identity, permissions, and audit layer for AI agents.

Vorim AI provides cryptographic agent identities (Ed25519), fine-grained permissions (7 scopes), immutable audit trails, and trust scoring (0-100) for production AI agent deployments. Built for the traceability and audit-trail obligations of frameworks like the EU AI Act.

PyPI Python License

API key: create one in the Vorim dashboard under Settings, API keys. No account yet? Request access at vorim.ai. Documentation — Full API reference, framework integrations, and examples. Quick Start — Set up in under 5 minutes.

Install

Requires Python 3.10+.

pip install vorim

With framework integrations (keep the quotes, zsh treats unquoted square brackets as a glob):

pip install "vorim[langchain]"    # LangChain / LangGraph
pip install "vorim[crewai]"       # CrewAI
pip install "vorim[openai]"       # OpenAI Agents SDK
pip install "vorim[all]"          # All integrations

Quick Start

The key for this quick start needs the agents:read, agents:write, permissions:read, audit:read and audit:write scopes. Scopes are independent, so agents:write does not include agents:read.

from vorim import Vorim

vorim = Vorim(api_key="agid_sk_live_...")

# Register an agent (returns Ed25519 keypair, private key shown once)
result = vorim.register(
    name="invoice-processor",
    capabilities=["read_documents", "extract_data"],
    scopes=["agent:read", "agent:execute"],
)
print(result.agent.agent_id)    # agid_acme_a1b2c3d4
print(result.agent.trust_score) # 50

# Check permissions (<5ms via Redis)
check = vorim.check(result.agent.agent_id, "agent:execute")

if check.allowed:
    # Emit audit event
    vorim.emit(
        agent_id=result.agent.agent_id,
        event_type="tool_call",
        action="process_invoice",
        resource="INV-2026-0042",
        result="success",
        latency_ms=142,
    )

# Verify any agent's trust (public, no auth required)
trust = vorim.verify(result.agent.agent_id)
print(f"Trust score: {trust.trust_score}/100")

Async Client

import asyncio

from vorim import AsyncVorim


async def main():
    async with AsyncVorim(api_key="agid_sk_live_...") as vorim:
        result = await vorim.register(
            name="my-agent",
            capabilities=["search"],
            scopes=["agent:read"],
        )

        trust = await vorim.verify(result.agent.agent_id)
        print(f"Trust score: {trust.trust_score}/100")


asyncio.run(main())

API Reference

Vorim(api_key, base_url?, timeout?, auto_sign=True)

Method Description
register(name, capabilities, scopes) Register an agent; caches the returned Ed25519 private key for auto-signing
check(agent_id, scope) Check if agent has permission (sub-5ms)
emit(agent_id, event_type, action, ..., sign=None) Emit an audit event. Auto-signed if the agent's key is in the keyring
emit_batch(events, sign=None) Emit up to 1,000 audit events. Auto-signs each one
verify(agent_id) Verify agent identity and trust score (public)
get_agent(agent_id) Get agent details
list_agents(status?, page?, per_page?) List agents with filtering
revoke(agent_id) Permanently revoke an agent
grant(agent_id, scope, valid_until?, rate_limit?) Grant a permission scope
use_agent_key(agent_id, private_key_pem) Restore a private key into the in-memory keyring after process restart
forget_agent_key(agent_id) Remove a private key from the keyring

Module-level helpers: canonical_payload_v1(event) and canonical_payload_v0(event) (return the bytes that get signed) and sign_payload(payload, private_key_pem) (returns ed25519:<base64>).

AsyncVorim has the same interface with await on all methods.

Per-event signing (auto-signing)

From v3.7.0, every audit event is signed at source with the agent's Ed25519 private key — no code change required. register() caches the returned key in memory and emit() attaches the signature transparently.

Canonical form. Since 3.7.0 the SDK defaults to v1 canonical form: RFC 8785 JSON Canonicalization Scheme (JCS) over the whole event minus signature and canonical_form. v1 brings metadata, replayable-evidence fields (model_version, tool_catalogue_hash, system_prompt_hash, prev_event_hash), and delegation context (on_behalf_of, delegator_agent_id, delegation_chain_id, delegation_depth) under the signature. The previous v0 form was a pipe-joined six-field string event_type|action|resource|input_hash|output_hash|result and is now deprecated — passing canonical_form="v0" explicitly still works for verifier-compat scenarios but logs a deprecation warning. Use @vorim/verify@0.2.0+ (or the v1 helpers in this package) to verify v1 events offline.

result = vorim.register(name="agent", capabilities=[], scopes=["agent:execute"])

# Auto-signed. The signature is attached before the request leaves the process.
vorim.emit(
    agent_id=result.agent.agent_id,
    event_type="tool_call",
    action="transfer_funds",
    result="success",
)

To verify signatures server-side, the API operator sets VORIM_VERIFY_AUDIT_SIGNATURES=true.

Restoring keys across process restarts. The in-memory keyring is lost on restart. Load the private key from your secret store:

vorim.use_agent_key(agent_id, private_key_pem)
vorim.forget_agent_key(agent_id)  # revoke from memory

Opting out. Per event with sign=False, or globally with auto_sign=False:

vorim.emit(agent_id=..., event_type=..., action=..., result=..., sign=False)
vorim = Vorim(api_key=..., auto_sign=False)

HTTP Message Signatures (RFC 9421)

An agent can sign the HTTP requests it sends, so the service on the other end can check which agent made the call and that nobody changed it on the way. The signature follows RFC 9421 and goes in the Signature-Input and Signature headers. When the request has a body, the SDK adds an RFC 9530 Content-Digest header and puts it under the signature, which ties the body to it too.

Signing uses the key that register() or use_agent_key() cached for that agent. keyid is the agent_id, the algorithm is ed25519, and tag is vorim.

import json
import httpx

body = json.dumps({"task": "summarise", "doc_id": "d_91"})
request = {
    "method": "POST",
    "url": "https://agent-b.example.com/tasks",
    "headers": {"content-type": "application/json"},
    "body": body,
}

signed = vorim.sign_http_request(agent_id, request)
httpx.post(request["url"], headers={**request["headers"], **signed["headers"]}, content=body)

On the receiving side, verify_http_request sends the request to Vorim. Vorim looks up the signing agent's registered public key and refuses agents that are suspended or revoked. The result also carries the agent's org name, status and trust score. Pass the raw body if you want the digest checked; content_digest_checked tells you whether it was.

result = vorim.verify_http_request(
    {"method": req.method, "url": str(req.url), "headers": dict(req.headers), "body": raw_body},
    max_age_seconds=300,
)
if not result["valid"]:
    raise PermissionError(result["reason"])
print(result["agent_id"], result["trust_score"])

You can also verify locally with a public key you already hold, with no call to Vorim. The module also signs with ECDSA P-256 keys (ecdsa-p256-sha256), which is the curve iOS Secure Enclave and Android StrongBox keys use.

from vorim.http_signatures import verify_http_request

result = verify_http_request(
    request,
    public_key=agent_public_key_pem,  # SPKI PEM, Ed25519 or P-256
    max_age_seconds=300,
    required_components=["@method", "@target-uri", "content-digest"],
)

AsyncVorim has the same two methods; verify_http_request is awaitable there. Signatures are byte-compatible with the TypeScript SDK, and the module passes the Ed25519 test vector in RFC 9421 Appendix B.2.6. It supports every derived component in the RFC, and the req, name and bs component parameters. sf, key and tr raise an error because they aren't supported yet.

Runtime Control (gate actions before they happen)

Ask Vorim whether an action should proceed before your agent performs it. before_action() returns a typed decision and, by default, raises on deny (a denial is in the response body, not the HTTP status).

from vorim import Vorim, VorimDeniedError

vorim = Vorim(api_key="agid_sk_live_...")

try:
    decision = vorim.before_action(
        agent_id="agid_acme_a1b2c3d4",      # always the public agid_* id
        action_type="tool_call",
        action_target="sendEmail",
        required_scope="agent:communicate",
        payload={"to": "customer@example.com", "body": "..."},
    )

    payload = decision.modified_payload or {"to": "customer@example.com"}

    if decision.decision in ("allow", "modify"):
        send_email(payload)
    elif decision.decision == "escalate":
        resolved = vorim.wait_for_decision_resolution(decision.decision_id)
        if resolved.decision == "allow":
            send_email(payload)

    # Link the post-action audit event back to the decision.
    vorim.emit(
        agent_id="agid_acme_a1b2c3d4",
        event_type="tool_call",
        action="sendEmail",
        result="success",
        decision_id=decision.decision_id,   # correlates audit ↔ decision
    )
except VorimDeniedError as err:
    print("Action denied:", err.decision.reason)

Verdicts: allow · deny (raises VorimDeniedError by default) · modify (use decision.modified_payload) · escalate (poll wait_for_decision_resolution) · fallback.

modify is client-cooperative. Vorim returns the sanitised modified_payload; your agent must send it in place of the original. The platform does not sit inline and does not currently enforce that you do — carry decision_id into the matching emit() so the action stays auditable.

Fail-open: if the decision API is unreachable, before_action() returns a synthetic fallback decision. Pass runtime_fail_open=False to the constructor to fail closed. A reachable server returning deny always denies. AsyncVorim exposes the same async methods.

Requires an API key with the runtime:decide scope and a Growth+ plan. modify verdicts come from policy rules provisioned by Vorim (rule-authoring API ships in a later release).

Permission Scopes

Scope Description
agent:read Read data on behalf of owner
agent:write Write or modify data
agent:execute Trigger actions or tool calls
agent:transact Financial or contractual actions
agent:communicate Send messages or emails
agent:delegate Sub-delegate to other agents
agent:elevate Request permission elevation

Payload Privacy

Your prompts and model outputs never have to reach Vorim. The audit event carries a digest of them, computed in your process.

A bare SHA-256 of a prompt is not a commitment, it is a lookup key: prompts are low-entropy and usually templated, so anyone holding the digest and the template recovers the content by trying candidates. Use a keyed commitment for anything a human or a model wrote.

from vorim import Vorim, commit_payload

key = os.environ["VORIM_COMMITMENT_KEY"]   # never sent to Vorim

v.emit(
    agent_id=agent.agent_id,
    event_type="tool_call",
    action="invoice.refund",
    result="success",
    input_hash=commit_payload(prompt, key),        # hmac-sha256:...
    output_hash=commit_payload(completion, key),
)

Keep hash_payload for content that is already high-entropy. To disclose later, hand the verifier the content and the key; they recompute and compare.

Refuse to send content at all:

v = Vorim(api_key=..., no_payload=True)          # no_payload_max_metadata_chars=256
v.emit(..., metadata={"prompt": full_prompt})    # raises VorimError PAYLOAD_BLOCKED

Not the same as the server-side Zero Data Retention setting, which drops metadata when we persist it, after the content has crossed the network. This means it never left your process.

Every emit returns a stable content digest beside the event id, and event_digest(event) recomputes it locally. Byte-identical to @vorim/sdk and @vorim/verify.

Framework Integrations

LangChain / LangGraph

from vorim import Vorim
from vorim.integrations.langchain import vorim_tool, VorimCallbackHandler

vorim = Vorim(api_key="agid_sk_live_...")

@vorim_tool(vorim, agent_id="agid_acme_...", permission="agent:execute")
def search(query: str) -> str:
    """Search documents."""
    return f"Results for {query}"

# search() is now a standard LangChain tool with built-in permission checks + audit

CrewAI

from vorim import Vorim
from vorim.integrations.crewai import register_crew

vorim = Vorim(api_key="agid_sk_live_...")

crew = register_crew(vorim, {
    "crew_name": "content-pipeline",
    "members": [
        {
            "role": "researcher",
            "name": "crew-researcher",
            "capabilities": ["web_search"],
            "scopes": ["agent:read", "agent:execute"],
        },
    ],
})

OpenAI Function Calling

from openai import OpenAI
from vorim import Vorim
from vorim.integrations.openai_agents import VorimToolRegistry

vorim = Vorim(api_key="agid_sk_live_...")
client = OpenAI()

registry = VorimToolRegistry(vorim=vorim, agent_id="agid_acme_...")
registry.add(
    name="search",
    description="Search documents",
    parameters={"type": "object", "properties": {"query": {"type": "string"}}},
    execute=lambda args: f"Results for {args['query']}",
)

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Search for AI papers"}],
    tools=registry.to_openai_tools(),
)

# Permission checked + audited automatically
tool_messages = registry.execute_tool_calls(
    response.choices[0].message.tool_calls or []
)

Resources

License

MIT

Release files for vorim 3.23.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vorim 3.23.0
File Size Uploaded
vorim-3.23.0.tar.gz 499.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vorim 3.23.0
File Interpreter ABI Platform
vorim-3.23.0-py3-none-any.whl Python 3 none any Details

Total release size: 719.4 kB

Release files / vorim-3.23.0.tar.gz

Download URL vorim-3.23.0.tar.gz
Size 499.3 kB
Tags Source
SHA-256 checksum
How to use checksums
c89b15514ce73699aaf8070fa2a8032cca5d20e3123e5f132e5863b232707c18
BLAKE2b-256 checksum
How to use checksums
e26bcf097386eead8a3dfe84f81560821db64ccea278b760674b90e1a8015f1f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.8

Release files / vorim-3.23.0-py3-none-any.whl

Download URL vorim-3.23.0-py3-none-any.whl
Size 220.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
596993cdff554f04eba005be41d8d87f6a3ecb411ff32fb5b089ae5d40e15eb7
BLAKE2b-256 checksum
How to use checksums
13d5b16ddc37388c730860e15d37c69b65adea5881bbdb593e9c83177ae0800c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.8

Release history Release notifications | RSS feed

This release

3.23.0 This release

2 release files

3.22.1

2 release files

3.22.0

2 release files

3.19.0

2 release files

3.18.2

2 release files

3.18.1

2 release files

3.18.0

2 release files

3.17.0

2 release files

3.16.0

2 release files

3.15.0

2 release files

3.11.1

2 release files

3.11.0

2 release files

3.10.5

2 release files

3.10.4

2 release files

3.10.3

2 release files

3.10.2

2 release files

3.10.1

2 release files

3.10.0

2 release files

3.9.2

2 release files

3.9.1

2 release files

3.9.0

2 release files

3.8.6

2 release files

3.8.5

2 release files

3.8.4

2 release files

3.8.3

2 release files

3.8.2

2 release files

3.8.1

2 release files

3.8.0

2 release files

3.7.3

2 release files

3.7.2

2 release files

3.7.0

2 release files

3.6.2

2 release files

3.6.1

2 release files

3.6.0

2 release files

3.5.0

2 release files

3.4.0

2 release files

3.3.1

2 release files

3.3.0

2 release files

3.2.0

2 release files

3.1.0

2 release files

3.0.0

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page