Skip to main content

Official Python SDK for AgentOS — observability, runtime, and security for AI agents.

Project description

agenthog (Python SDK for AgentOS)

Official Python SDK for AgentOS — observability, runtime, and security for AI agents. Currently at v0.1.0.

The package is named agenthog because AgentHog is the developer-facing observability surface of the AgentOS platform; the SDK ships those primitives under that name. (The platform itself is still called "AgentOS" and the GitHub repo is still agentos-python.)

Install

pip install agenthog
# auto-instrumentation extras (each is opt-in):
pip install "agenthog[openai]"
pip install "agenthog[anthropic]"
pip install "agenthog[langchain]"
pip install "agenthog[otel]"
# or everything at once:
pip install "agenthog[all]"

Requires Python 3.10 or newer.

First trace (5 lines)

import agenthog

agenthog.init(api_key="agops_…", agent_id="my-agent")

with agenthog.start_task_run() as run:
    # Your agent logic here. Auto-instrumented LLM / tool calls land
    # automatically; manual events go through `client.log_*(...)`.
    ...

That's it. Every supported integration emits the same agent.* event shape so your traces look the same regardless of which framework you end up calling.

Quickstart with auto-instrumentation

import os
import agenthog
from openai import OpenAI

agenthog.init(api_key=os.environ["AGENTOS_API_KEY"], agent_id="weather-agent")
agenthog.autoinstrument()  # patches every LLM SDK importable in this process

client = OpenAI()
with agenthog.start_task_run() as run:
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": "Weather in Paris?"}],
    )
    print(resp.choices[0].message.content)

That's the entire setup. autoinstrument() detects whichever LLM SDKs you have installed (openai, anthropic, langchain) and wires up the matching agenthog.integrations.X.install() for each. It returns the list of installed integrations so you can verify what got wired up — e.g. print(agenthog.autoinstrument()) shows ['openai']. The function is idempotent and never raises; a broken integration is logged and skipped while the others still install.

Selective control

agenthog.autoinstrument(only=["openai"])              # patch openai, leave the rest
agenthog.autoinstrument(skip=["langchain"])           # patch everything except langchain

Per-integration install (power users)

The auto path is sugar on top of explicit per-integration installs. Use them directly when you want fine control or you only need one:

from agenthog.integrations import openai as openai_integration
openai_integration.install()                          # equivalent to autoinstrument(only=["openai"])

Each integration ships an install() / uninstall() pair. They are transparent: original return values pass through and original exceptions re-raise unchanged.

One uniform pattern for every provider

Most LLM providers — OpenAI, Anthropic, Mistral, Moonshot/Kimi, DeepSeek, Groq, Together, Fireworks, Perplexity, xAI, OpenRouter, local Ollama / vLLM / LM Studio — expose an OpenAI-compatible endpoint. So the same five lines above work for every one of them; only base_url, api_key, and model change:

client = OpenAI(
    base_url=os.environ["LLM_BASE_URL"],              # e.g. https://api.anthropic.com/v1/
    api_key=os.environ["LLM_API_KEY"],
)
resp = client.chat.completions.create(
    model=os.environ["LLM_MODEL"],                    # e.g. claude-sonnet-4-6
    messages=[{"role": "user", "content": "..."}],
)

The SDK inspects client.base_url and tags each trace with the correct upstream provider via gen_ai.system — so a call routed through OpenRouter shows up as openrouter in your dashboard, not openai.

Configuration

The SDK reads environment variables first; explicit init(...) args override. Full set per docs/spec/05-sdk-contract.md:

Field Env var Default
api_key AGENTOS_API_KEY (required)
endpoint AGENTOS_ENDPOINT https://api.theagentos.space
environment AGENTOS_ENV unset
agent_id AGENTOS_AGENT_ID unset (must be set here or at start_task_run)
workspace_id AGENTOS_WORKSPACE_ID resolved server-side from API key
capture_content True (set False to strip input / output / tool.input / tool.output)
flush_interval_ms 250
flush_batch_size 100
buffer_max_size 10000 (drop oldest on overflow)
disable AGENTOS_DISABLE False (1 / true ⇒ fast no-op)
kind "sync" (or "async" for async-native hosts)

disable=True makes every public method a fast return — useful in unit tests that don't want a mock endpoint.

Integrations

Provider Module Patches
OpenAI agenthog.integrations.openai chat.completions.create (sync + async, streaming + non-streaming, tool calls)
Anthropic agenthog.integrations.anthropic messages.create (with stream=True) and messages.stream
LangChain agenthog.integrations.langchain BaseCallbackHandler registered globally; one event per LLM call regardless of token count
OpenTelemetry passthrough agenthog.integrations.opentelemetry TEE: translates OTel spans to agent.* events; optional forward_to= keeps your collector

All integrations honor capture_content=False and emit exactly one event per logical operation — streaming aggregations close into a single agent.llm_call event with the full output and final usage.

Manual logging

Use client.log_* for anything not auto-instrumented:

client = agenthog.get_default_client()
assert client is not None

client.log_eval("faithfulness", score=0.92, evaluator="llm")
client.log_business_event("checkout_completed", revenue=29.0, currency="USD")
client.log_security_alert("prompt_injection", severity="high", action_taken="blocked")
client.log_handoff("researcher_agent", reason="needs deep search")
client.log_retrieval("vector_kb", query="...", top_k=5, results_count=3)

All inherit the active identity context. All validate locally; failed validation drops the event with a WARN — your code never raises.

Flags

variant = client.flag("use_gpt4_for_support", default=False, user_id="user_42")

The SDK polls GET /v1/flags every 60 s and evaluates locally (priority-ascending, first-match-wins; percentage rollouts use a stable hash so the same user stays in or out across calls). Each flag() call also emits an agent.flag_check event so you can correlate flag state with downstream behavior.

Routing

decision = client.route(goal="answer_well", context={"topic": "support"})
# decision -> {"arm_id": "...", "model": "...", "decision_span_id": "..."}

# Later, after the model answers, close the bandit's loop:
client.route_outcome(decision["decision_span_id"], reward=1.0, success=True, feedback_kind="auto")

Inside an AgentRun container (AGENTOS_RUNTIME=1), route and route_outcome go through the syscall mediator sidecar over a Unix socket — same SDK code path, no env var to flip.

Privacy controls

  • capture_content=False strips input, output, tool.input, tool.output, retrieval.query, retrieval.documents from every emitted event. Token counts, model names, durations, costs, and identity fields still flow.
  • Redactors run before send: client.add_redactor(lambda e: ...). Redactors must be deterministic and fast; if one raises, it's skipped (with a WARN) and the event still ships.
  • The SDK detects email / E.164 phone patterns in user_id and emits a one-time WARN per id so you can pseudonymize before they hit the wire.

SDK logs

Internal SDK logs live under the agenthog.sdk namespace, default level WARNING. Silence or amplify via standard Python logging:

import logging
logging.getLogger("agenthog.sdk").setLevel(logging.DEBUG)

Sub-loggers per submodule: agenthog.sdk.transport, agenthog.sdk.context, agenthog.sdk.runtime, agenthog.sdk.integrations.<name>, agenthog.sdk.flags.

Failure-mode contract

Per docs/spec/05-sdk-contract.md "Failure modes": the SDK never raises out of public methods. A misconfigured endpoint, a network outage, a malformed event — every error flows to the internal logger and the corresponding metric counter, never to your application.

Counters live on client.metrics:

  • events_sent — successfully ingested
  • events_dropped — buffer overflow
  • events_validation_failed — schema rejection (local)
  • events_retried — retried at least once before success or permanent-fail
  • events_failed_permanent — gave up after max_retries

Hook into them via client.on_metric(lambda name, delta: ...).

Versioning (SemVer)

  • Patch (0.1.00.1.1): new event types, new optional fields, bug fixes.
  • Minor (0.1.00.2.0) while still in 0.x: any breaking change to public methods.
  • Major (0.x1.0.0): graduation to stable.
  • Once on 1.x, breaking changes bump major.

The __version__ constant in agenthog/__init__.py and the version field in pyproject.toml are kept in sync; the publish workflow refuses to ship if the tag and __version__ disagree.

Local development

uv sync
uv run pytest -q
uv run mypy agenthog/
uv run ruff check . && uv run ruff format .

Integration tests

The end-to-end test in tests/integration/test_e2e.py runs against a live AgentOS platform. It is skipped automatically unless both env vars are set:

export AGENTOS_TEST_ENDPOINT=https://api.theagentos.space
export AGENTOS_TEST_API_KEY=agops_…
# Optional override:
export AGENTOS_TEST_AGENT_ID=e2e-test-agent

uv run pytest tests/integration/test_e2e.py -v

The test mocks the OpenAI client (no real API costs) but every event flows through the actual transport, hits the actual ingestion API, and is read back via GET /v1/traces/:trace_id.

Publishing

This repo publishes via Trusted Publishing (OpenID Connect) — no API tokens stored anywhere. Two workflows:

One-time setup (per index — TestPyPI and PyPI are independent):

  1. Register the project on the index (one manual upload is enough to claim the agenthog name on each).
  2. On the project's "Publishing" settings page, add a Trusted Publisher with:
    • Owner: your GitHub user / org.
    • Repository: agentos-python.
    • Workflow: publish.yml (PyPI) or publish-test.yml (TestPyPI).
    • Environment: pypi or testpypi respectively.
  3. In this repo's GitHub settings → Environments, create the matching environment(s). No required reviewers — the OIDC handshake is the gate.

Recommended release flow:

# 1. Dry-run on TestPyPI: Actions → publish-test → Run workflow → main
pip install -i https://test.pypi.org/simple/ \
  --extra-index-url https://pypi.org/simple/ \
  agenthog==0.1.0
# … smoke-test in a fresh venv …

# 2. Tag for production
git tag v0.1.0
git push origin v0.1.0

The publish workflow builds, verifies the tag matches __version__, and publishes to PyPI.

main branch protection requires the test workflow to pass before merge.

Spec

The four spec files this SDK honors live under docs/spec/:

When spec and code disagree, fix the spec first. Same rule as the platform monorepo.

License

Apache License 2.0. The published agenthog package on PyPI ships under the same terms — including the explicit patent grant and the standard "AS IS" disclaimer in section 7 of the license. The package contains no code from the AgentOS platform monorepo; only the SDK client surface defined in docs/spec/05-sdk-contract.md.

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

agenthog-0.2.0.tar.gz (91.0 kB view details)

Uploaded Source

Built Distribution

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

agenthog-0.2.0-py3-none-any.whl (115.8 kB view details)

Uploaded Python 3

File details

Details for the file agenthog-0.2.0.tar.gz.

File metadata

  • Download URL: agenthog-0.2.0.tar.gz
  • Upload date:
  • Size: 91.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for agenthog-0.2.0.tar.gz
Algorithm Hash digest
SHA256 cceb6cd7b4443eebbcb9f5c56da6b8f82d32562ff5f8725dfce02822ba2066d1
MD5 0d7d4c15d26542bd55de03c442e45cd8
BLAKE2b-256 2dc766f6763771e73f9906c1b57a6aa49e801aeaff7f01521cfa45c5ef0162c0

See more details on using hashes here.

File details

Details for the file agenthog-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: agenthog-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 115.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for agenthog-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 85a78231dd5309b3001ba75d1837761a18a19a17f9174f9600d73a528bdc33bd
MD5 539ca6357ced54bb2dd21f6d66c9fea8
BLAKE2b-256 9330768630d13d9d7fb3f81fd9025156be96ada1307ee99eaf121cacabea0d19

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