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.5.0.tar.gz (98.1 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.5.0-py3-none-any.whl (124.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: agenthog-0.5.0.tar.gz
  • Upload date:
  • Size: 98.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for agenthog-0.5.0.tar.gz
Algorithm Hash digest
SHA256 426a0e9cb527d15018a819f4724ecaf107e71c5e95f8cef7eb6fd9f911252279
MD5 f852e535864dc18515c2bf5392f33fcb
BLAKE2b-256 c113bedfd8b597525a0de6beccd360b55a50c031519e01cae6ab2185b2a7d230

See more details on using hashes here.

Provenance

The following attestation bundles were made for agenthog-0.5.0.tar.gz:

Publisher: publish.yml on TheAgentOS/agentos-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: agenthog-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 124.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for agenthog-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a67fc50f0c01f5e3fd53d68afe5394619b9a738b614c29b71c5727b647633700
MD5 27b883e384687312b0cac691fc9b57fa
BLAKE2b-256 a51c94cc8cb81f802cc4a99fb34380f537cc19d1bef595165a4c68bcb7f15f06

See more details on using hashes here.

Provenance

The following attestation bundles were made for agenthog-0.5.0-py3-none-any.whl:

Publisher: publish.yml on TheAgentOS/agentos-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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