agenthog-setup

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Agenthog setup

Agenthog 设置

You (the AI coding agent reading this skill) are being asked to install and configure AgentHog tracing in the user's project. Follow this skill end-to-end. Do NOT skip the verification step.
你(正在阅读此 skill 的 AI 编码 Agent)需要安装并配置用户项目中的 AgentHog 追踪。请完整执行此 skill。 不得跳过验证步骤。

1. Detect the runtime

1. 检测运行时

Look at the project root to determine the language and primary framework:
  • Python if you see
    pyproject.toml
    ,
    requirements.txt
    ,
    setup.py
    , or
    *.py
    files.
  • TypeScript / Node if you see
    package.json
    with
    "type": "module"
    or TypeScript files, or
    tsconfig.json
    .
If both, default to whichever the primary entrypoint uses. Ask the user if genuinely ambiguous.
Identify the primary framework: FastAPI, Flask, Django, LangGraph, LangChain, Express, Vercel AI SDK, Next.js, Hono, etc. The framework determines where
init
belongs and where the per-request loop is.
查看项目根目录,以确定语言和主要框架:
  • Python:如果看到
    pyproject.toml
    、
    requirements.txt
    、
    setup.py
    或
    *.py
    文件。
  • TypeScript / Node:如果看到带
    "type": "module"
    的
    package.json
    、TypeScript 文件或
    tsconfig.json
    。
如果两者都有,默认使用主要入口点所采用的运行时。仅当确实存在歧义时才询问用户。
识别主要框架:FastAPI、Flask、Django、LangGraph、LangChain、Express、Vercel AI SDK、Next.js、Hono 等。框架决定
init
的位置以及每次请求循环所在的位置。

2. Gather configuration

2. 收集配置

Two values are required from the user. The endpoint is auto-defaulted — do NOT ask the user about it unless one of the override conditions below fires.
需要用户提供两个值。Endpoint 会自动使用默认值——除非触发下述覆盖条件,否则不要询问用户。

Required:
AGENTOS_API_KEY
and
AGENTOS_WORKSPACE_ID

必需项:
AGENTOS_API_KEY
和
AGENTOS_WORKSPACE_ID

These are secrets, resolved at runtime from the environment — the SDK reads
AGENTOS_API_KEY
/
AGENTOS_WORKSPACE_ID
from env vars (see the
init
examples below). Your job is to wire the code to those env vars and confirm the values are present — never to obtain, see, or store the secret yourself.
  1. Already in the environment? (
    AGENTOS_API_KEY
    ,
    AGENTOS_WORKSPACE_ID
    set) — good, nothing to gather. Wire the code to read them and move on.
  2. Not set? The user provides them — you never handle the secret. Offer two ways and prefer the first. A bare
    export
    is per-shell and dies when the terminal closes — a common cause of "it traced once, then stopped," and it's invisible to any other shell (including your own tool shell):
    • Preferred —
      agenthog init
      (
      agenthog >= 0.5.0
      ): prompts for both values, writes a gitignored
      .env
      (
      0600
      ), and persists across restarts and across shells. The user runs it and types the key; you do not. Because it writes
      .env
      , the values survive new terminals — no two-shells mismatch.
    • Fallback — shell
      export
      (ephemeral, fine for a quick one-off): the user sets the values in the terminal where they'll run the app:
      bash
      export AGENTOS_API_KEY=<their key>
      export AGENTOS_WORKSPACE_ID=<their workspace id>
      The quickstart page gives a ready-to-paste
      export
      block. This lasts only for that shell session — recommend
      agenthog init
      for anything persistent.
    Get values from https://app.theagentos.space (API key: Settings → API Keys; workspace ID: sidebar chip / top-right). Once the user has done one of these, confirm presence by name (below) and continue.
Confirm presence without ever reading the secret:
Check that the vars are set, never their value — a boolean presence test, never
cat .env
or echoing the key into your context:
bash
undefined
这些是机密信息,在运行时从环境变量解析——SDK 会从环境变量读取
AGENTOS_API_KEY
/
AGENTOS_WORKSPACE_ID
(参见下面的
init
示例)。你的工作是将代码接入这些环境变量并确认变量已存在——绝不获取、查看或自行保存机密值。
  1. 环境中已存在?(已设置
    AGENTOS_API_KEY
    、
    AGENTOS_WORKSPACE_ID
    )——很好,无需收集任何内容。将代码接入并读取这些变量,然后继续。
  2. 尚未设置?由用户提供——你绝不处理机密值。提供两种方式,并优先使用第一种。直接使用
    export
    仅对当前 shell 有效,终端关闭后就会失效——这是“只追踪了一次,然后停止”的常见原因,而且该问题对其他 shell(包括你自己的工具 shell)不可见:
    • 首选——
      agenthog init
      (
      agenthog >= 0.5.0
      ):会提示用户输入两个值,将凭据写入被 gitignore 的
      .env
      (权限为
      0600
      ),并在重启及不同 shell 之间持续生效。由用户运行并输入密钥;你不能代替用户输入。由于它会写入
      .env
      ,这些值可跨新终端保留,不会出现两个 shell 配置不一致的问题。
    • 备选——shell
      export
      (临时方案,适合快速一次性使用):用户在运行应用的终端中设置这些值:
      bash
      export AGENTOS_API_KEY=<their key>
      export AGENTOS_WORKSPACE_ID=<their workspace id>
      快速入门页面提供了一个可直接粘贴的
      export
      代码块。该配置仅在当前 shell 会话中有效——任何需要持久生效的场景都应推荐使用
      agenthog init
      。
    用户可从 https://app.theagentos.space 获取这些值(API key:Settings → API Keys;workspace ID:侧边栏 chip / 右上角)。用户完成其中一种配置后,按变量名确认其存在(见下文),然后继续。
确认变量存在,但绝不读取机密值:
检查变量是否已设置,而不是读取其值——只做布尔存在性测试,绝不执行
cat .env
,也绝不将密钥回显到上下文中:
bash
undefined

prints only yes/no; resolves env first, then a gitignored .env the app loads

prints only yes/no; resolves env first, then a gitignored .env the app loads

python3 -c "import os; print('AGENTOS_API_KEY set:', bool(os.getenv('AGENTOS_API_KEY')))"

If it prints `False`, the user hasn't completed `agenthog init` / `export` yet —
ask them to finish, don't go hunting for the value.

**Credential safety (do not deviate):**

- **Never accept the API key pasted into the chat.** If a user offers to paste
  it, decline and tell them to run `agenthog init` (or `export` it) instead —
  you reference `AGENTOS_API_KEY` by name, never the value.
- **Never search the filesystem or read files hunting for a key**, and never
  open `.env` to read the secret. Confirm presence by env-var name only (above).
- **Never hardcode the key** in source, and **never print or echo it.** The
  code references `AGENTOS_API_KEY` via the environment, never a literal.
- **The agent never writes the plaintext secret to disk.** `agenthog init`
  (driven by the user typing their key) or the user does that. You may create or
  update `.env.example` with a **placeholder** (Step 6); the real value is never
  yours to handle.
python3 -c "import os; print('AGENTOS_API_KEY set:', bool(os.getenv('AGENTOS_API_KEY')))"

如果输出 `False`,说明用户尚未完成 `agenthog init` / `export`——请让用户完成操作,不要自行查找该值。

**凭据安全要求(不得偏离):**

- **绝不接受粘贴到聊天中的 API key。**如果用户主动粘贴,应拒绝,并告知其改为运行 `agenthog init`(或自行 `export`)——只按名称引用 `AGENTOS_API_KEY`,绝不引用其值。
- **绝不搜索文件系统或读取文件来查找密钥**,也绝不打开 `.env` 读取机密值。只按环境变量名确认其存在(如上)。
- **绝不在源代码中硬编码密钥**,也绝不打印或回显。代码通过环境变量引用 `AGENTOS_API_KEY`,绝不能使用字面量。
- **Agent 绝不将明文机密写入磁盘。**由 `agenthog init`(用户在提示下输入密钥)写入,或者由用户自行完成。你可以创建或更新 `.env.example`,但其中只能包含**占位符**(步骤 6);真实值绝不能由你处理。

Endpoint: default silently

Endpoint:静默使用默认值

AGENTOS_ENDPOINT
resolves in this order without prompting the user:
  1. If
    AGENTOS_ENDPOINT
    is already set in the environment, use that.
  2. Otherwise, use the default:
    https://api.theagentos.space
    .
Only prompt the user about the endpoint if you have positive evidence they want to override it — e.g. they said something like "I'm self-hosting" or "we run agenthog on our own infra" in their request.
Otherwise: pick the default and move on. Asking for the endpoint on every quickstart is annoying friction for the 95% who use the hosted cloud.
Never commit the plaintext API key, and don't write it to disk yourself — the user places the real value (Step 6 wires the code + the
.env.example
placeholder).
AGENTOS_ENDPOINT
按以下顺序解析,期间不提示用户:
  1. 如果环境中已设置
    AGENTOS_ENDPOINT
    ,则使用该值。
  2. 否则使用默认值:
    https://api.theagentos.space
    。
仅当有明确证据表明用户希望覆盖默认值时,才询问 Endpoint——例如用户表示“我要自托管”或“我们在自己的基础设施上运行 agenthog”。
否则,直接选择默认值并继续。对于 95% 使用托管云的用户,每次快速入门都询问 Endpoint 会造成不必要的摩擦。
绝不提交明文 API key,也绝不自行将其写入磁盘——真实值由用户放置(步骤 6 负责接入代码并提供
.env.example
占位符)。

3. Install the SDK (a new-enough version is mandatory)

3. 安装 SDK(必须使用足够新的版本)

Minimum supported version: Python
agenthog >= 0.9.0
, TypeScript
agenthog >= 0.3.0
.
The ingestion API rejects events from older SDKs (HTTP 426). The Python floor is 0.9.0 because this skill depends on its features end-to-end:
agenthog init
credentials (0.5.0), raw-HTTP LLM capture for OpenAI-compatible endpoints + automatic flush-on-exit (0.6.0), the
@agenthog.tool
/
@traceable
decorator for tracing the agent's tools (0.7.0), and one-call tool capture
instrument_module
(Step 5b, 0.9.0)
— which guarantees no tool is silently missed. Below the floor, setup produces incomplete traces (missing tool steps, or none at all from a short-lived process).
Install (or upgrade)
agenthog
as part of setup, using the project's existing package manager — the same one already managing its dependencies. Tell the user what you're adding, and pin the floor so an existing older install is bumped rather than left as-is. If you can't determine the package manager, ask before installing.
最低支持版本:Python
agenthog >= 0.9.0
,TypeScript
agenthog >= 0.3.0
。
摄取 API 会拒绝旧版 SDK 发送的事件(HTTP 426)。Python 最低版本为 0.9.0,因为此 skill 的完整功能依赖其特性:凭据初始化
agenthog init
(0.5.0)、面向 OpenAI 兼容端点的原始 HTTP LLM 捕获及退出时自动 flush(0.6.0)、用于追踪 Agent 工具的
@agenthog.tool
/
@traceable
装饰器(0.7.0),以及一次调用即可完成工具捕获的
instrument_module
(步骤 5b,0.9.0)
——这可确保不会静默遗漏任何工具。低于最低版本时,设置只会生成不完整的 trace(缺少工具步骤,或者短生命周期进程完全没有 trace)。
作为设置的一部分安装(或升级)
agenthog
,并使用项目现有的包管理器——即当前负责管理项目依赖的同一个工具。告知用户新增了哪些依赖,并锁定最低版本,确保已有的旧版本被升级,而不是继续保留。如果无法确定包管理器,应先询问用户再安装。

Python

Python

Detect the package manager (
uv
,
poetry
,
pip
,
pipenv
) and install with the version floor + upgrade:
bash
undefined
检测包管理器(
uv
、
poetry
、
pip
、
pipenv
),使用带版本下限及升级选项的命令安装:
bash
undefined

uv (uv add always resolves to the newest allowed; the floor guarantees ≥0.9.0)

uv (uv add always resolves to the newest allowed; the floor guarantees ≥0.9.0)

uv add 'agenthog>=0.9.0'
uv add 'agenthog>=0.9.0'

poetry

poetry

poetry add 'agenthog@>=0.9.0'
poetry add 'agenthog@>=0.9.0'

pip (-U upgrades an already-installed older copy)

pip (-U upgrades an already-installed older copy)

pip install -U 'agenthog>=0.9.0'

For frameworks with first-class auto-instrumentation, install the extras:

```bash
pip install -U 'agenthog>=0.9.0'

对于具备一等自动埋点支持的框架,安装相应的 extras:

```bash

OpenAI calls

OpenAI calls

uv add 'agenthog[openai]>=0.9.0'
uv add 'agenthog[openai]>=0.9.0'

Anthropic

Anthropic

uv add 'agenthog[anthropic]>=0.9.0'
uv add 'agenthog[anthropic]>=0.9.0'

LangChain / LangGraph

LangChain / LangGraph

uv add 'agenthog[langchain]>=0.9.0'
uv add 'agenthog[langchain]>=0.9.0'

OpenTelemetry passthrough

OpenTelemetry passthrough

uv add 'agenthog[otel]>=0.9.0'
undefined
uv add 'agenthog[otel]>=0.9.0'
undefined

TypeScript

TypeScript

bash
undefined
bash
undefined

pnpm (preferred)

pnpm (preferred)

pnpm add agenthog@latest
pnpm add agenthog@latest

npm

npm

npm install agenthog@latest
npm install agenthog@latest

yarn

yarn

yarn add agenthog@latest
yarn add agenthog@latest

bun

bun

bun add agenthog@latest

Auto-instrumentation in TS is wired via the integrations import — no extras
required at install time. See `reference/typescript.md`.
bun add agenthog@latest

TypeScript 中的自动埋点通过 integrations 导入接入——安装时不需要额外的 extras。参见 `reference/typescript.md`。

Verify the installed version satisfies the floor (do not skip)

验证已安装版本满足最低要求(不得跳过)

After installing, confirm the version (Python
>= 0.9.0
, TypeScript
>= 0.3.0
). If it isn't, upgrade and re-check before continuing — the rest of the setup (and the ingestion API) assumes it.
bash
undefined
安装后,确认版本符合要求(Python
>= 0.9.0
,TypeScript
>= 0.3.0
)。如果不符合,应先升级并重新检查,再继续——后续设置及摄取 API 都依赖此版本。
bash
undefined

Python — prints the installed version; exits non-zero if below the floor.

Python — prints the installed version; exits non-zero if below the floor.

python -c "import agenthog, sys; from importlib.metadata import version;
v=version('agenthog'); print('agenthog', v);
sys.exit(0 if tuple(map(int, v.split('.')[:2])) >= (0,9) else 1)"
python -c "import agenthog, sys; from importlib.metadata import version;
v=version('agenthog'); print('agenthog', v);
sys.exit(0 if tuple(map(int, v.split('.')[:2])) >= (0,9) else 1)"

TypeScript — same idea.

TypeScript — same idea.

node -e "const v=require('agenthog/package.json').version; const [a,b]=v.split('.').map(Number);
console.log('agenthog', v); process.exit((a>0||b>=3)?0:1)"

If the check reports a version below the floor (Python `0.9.0`, TypeScript
`0.3.0`), upgrade it the same way you installed it (the package manager's
upgrade for `agenthog`) and re-run the check. If the floor still can't be met
(e.g. the registry hasn't published it yet), **stop and tell the user** rather
than proceeding on an unsupported version — their telemetry would be rejected at
ingest, or the trace would be missing tool steps.
node -e "const v=require('agenthog/package.json').version; const [a,b]=v.split('.').map(Number);
console.log('agenthog', v); process.exit((a>0||b>=3)?0:1)"

如果检查结果低于最低版本(Python `0.9.0`、TypeScript `0.3.0`),请使用安装时相同的包管理器升级 `agenthog`,然后重新运行检查。如果仍无法满足最低要求(例如版本尚未发布到 registry),**请停止并告知用户**,不要继续使用不受支持的版本——否则其遥测数据会在摄取时被拒绝,或者 trace 中缺少工具步骤。

4. Wire
init
at app startup

4. 在应用启动时接入
init

The
init
call must run once, before any LLM/tool call you want traced. Place it in the app's primary entrypoint:
FrameworkWhere to call init
FastAPI
main.py
, before
app = FastAPI()
Flask
app.py
, before
app = Flask(__name__)
Django
settings.py
bottom, or an
apps.py
ready()
hook
LangGraph scripttop of the script, before graph construction
Express
index.ts
/
server.ts
, before
app.listen
Next.js
instrumentation.ts
(Next.js's official OTel/tracing hook)
Vercel AI SDKwherever the AI client is constructed
init
调用必须只运行一次,并且位于任何需要追踪的 LLM 或工具调用之前。 将其放在应用的主要入口点:
框架
init
的调用位置
FastAPI
main.py
中,位于
app = FastAPI()
之前
Flask
app.py
中,位于
app = Flask(__name__)
之前
Django
settings.py
底部,或
apps.py
的
ready()
hook 中
LangGraph 脚本脚本顶部,位于构建 graph 之前
Express
index.ts
/
server.ts
中,位于
app.listen
之前
Next.js
instrumentation.ts
(Next.js 官方的 OTel/追踪 hook)
Vercel AI SDK构建 AI client 的位置

Python init pattern

Python init 模式

python
import os
import agenthog

agenthog.init(
    api_key=os.environ["AGENTOS_API_KEY"],
    endpoint=os.environ.get("AGENTOS_ENDPOINT", "https://api.theagentos.space"),
    workspace_id=os.environ["AGENTOS_WORKSPACE_ID"],
    agent_id="<descriptive-agent-name>",  # pick based on what this service is
)
python
import os
import agenthog

agenthog.init(
    api_key=os.environ["AGENTOS_API_KEY"],
    endpoint=os.environ.get("AGENTOS_ENDPOINT", "https://api.theagentos.space"),
    workspace_id=os.environ["AGENTOS_WORKSPACE_ID"],
    agent_id="<descriptive-agent-name>",  # pick based on what this service is
)

Auto-instrument supported LLM / framework libraries. Detects installed

Auto-instrument supported LLM / framework libraries. Detects installed

packages (openai, anthropic, langchain) and patches them. As of

packages (openai, anthropic, langchain) and patches them. As of

agenthog >= 0.6.0 it ALSO captures raw-HTTP calls to OpenAI-compatible

agenthog >= 0.6.0 it ALSO captures raw-HTTP calls to OpenAI-compatible

/chat/completions endpoints made via
requests
or
httpx
— so agents that

/chat/completions endpoints made via
requests
or
httpx
— so agents that

POST directly to NVIDIA, Together, Groq, OpenRouter, a local vLLM/Ollama,

POST directly to NVIDIA, Together, Groq, OpenRouter, a local vLLM/Ollama,

etc. (instead of through a vendor SDK) get traced with no code change.

etc. (instead of through a vendor SDK) get traced with no code change.

agenthog.autoinstrument()

> **Provider coverage.** `autoinstrument()` (>= 0.6.0) covers the vendor SDKs
> **and** raw-HTTP OpenAI-compatible calls. If the agent talks to a *custom or
> non-OpenAI-shaped* endpoint that neither path recognizes, the LLM call won't
> be auto-captured — log it explicitly with `agenthog.emit("agent.llm_call",
> {...})` (or `log_tool_call` for tools, Step 5b). When verifying (Step 7),
> confirm the trace actually shows the LLM step, not just an empty `task_run`.

> **Flushing on exit is automatic** in agenthog >= 0.6.0: `init()` registers an
> `atexit` + `SIGTERM` drain, so short-lived CLIs / scripts deliver their buffer
> without a manual `flush()`. Only a hard kill (`SIGKILL`, `os._exit`) bypasses
> it — call `agenthog.shutdown()` before such an exit if you have one.
agenthog.autoinstrument()

> **Provider 覆盖范围。**`autoinstrument()`(>= 0.6.0)既覆盖厂商 SDK,也覆盖原始 HTTP OpenAI 兼容调用。如果 Agent 连接的是*自定义或非 OpenAI 格式*的 endpoint,且上述两种方式都无法识别,则 LLM 调用不会被自动捕获——应显式记录为 `agenthog.emit("agent.llm_call", {...})`(工具则使用 `log_tool_call`,见步骤 5b)。验证时(步骤 7),应确认 trace 确实显示了 LLM 步骤,而不仅仅是一个空的 `task_run`。

> `agenthog >= 0.6.0` 会**在退出时自动 flush**:`init()` 会注册 `atexit` + `SIGTERM` 排空机制,因此短生命周期 CLI/脚本无需手动调用 `flush()` 即可发送缓冲区内容。只有强制终止(`SIGKILL`、`os._exit`)会绕过此机制——如果存在此类退出路径,应在退出前调用 `agenthog.shutdown()`。

TypeScript init pattern

TypeScript init 模式

ts
import { init } from "agenthog";

init({
  apiKey: process.env.AGENTOS_API_KEY!,
  endpoint: process.env.AGENTOS_ENDPOINT ?? "https://api.theagentos.space",
  workspaceId: process.env.AGENTOS_WORKSPACE_ID!,
  agentId: "<descriptive-agent-name>",
});

// Auto-instrumentation is per-integration in TS. Import the wrapper for the
// LLM client you use. Examples:
//   import "agenthog/integrations/openai";
//   import "agenthog/integrations/anthropic";
//   import "agenthog/integrations/vercelAI";
//   import "agenthog/integrations/langchain";
Pick a
agentId
that describes what the service does, not just the repo name. Examples:
customer-support-bot
,
code-review-agent
,
etl-pipeline
.
ts
import { init } from "agenthog";

init({
  apiKey: process.env.AGENTOS_API_KEY!,
  endpoint: process.env.AGENTOS_ENDPOINT ?? "https://api.theagentos.space",
  workspaceId: process.env.AGENTOS_WORKSPACE_ID!,
  agentId: "<descriptive-agent-name>",
});

// Auto-instrumentation is per-integration in TS. Import the wrapper for the
// LLM client you use. Examples:
//   import "agenthog/integrations/openai";
//   import "agenthog/integrations/anthropic";
//   import "agenthog/integrations/vercelAI";
//   import "agenthog/integrations/langchain";
选择一个能够描述服务用途的
agentId
,而不要只使用仓库名称。例如:
customer-support-bot
、
code-review-agent
、
etl-pipeline
。

5. Wrap the primary agent loop in
start_task_run

5. 使用
start_task_run
包裹主要 Agent 循环

One
task_run
= one end-to-end execution of the agent (one user message → one final response, or one cron trigger → one job complete). Spans nest inside it.
一个
task_run
= 一次 Agent 的端到端执行(一条用户消息 → 一条最终响应,或一次 cron 触发 → 一次任务完成)。所有 Span 都会嵌套在其中。

Python — context manager

Python——上下文管理器

python
with agenthog.start_task_run(user_id=user_id) as ctx:
    # Auto-instrumented LLM calls in here are traced under one task_run_id.
    # Tool calls are NOT auto-traced unless they go through a framework
    # (LangChain/LangGraph) — see Step 5b for hand-written tool loops.
    result = my_agent.run(user_input)
    return result
Available kwargs:
agent_id
,
task_run_id
,
trace_id
,
user_id
,
session_id
. There is no
metadata=
kwarg — attach attribution via the explicit kwargs above instead.
For an HTTP handler (FastAPI/Flask), wrap the handler body:
python
@app.post("/chat")
async def chat(req: ChatRequest):
    with agenthog.start_task_run(user_id=req.user_id):
        return await my_agent.run(req.message)
python
with agenthog.start_task_run(user_id=user_id) as ctx:
    # Auto-instrumented LLM calls in here are traced under one task_run_id.
    # Tool calls are NOT auto-traced unless they go through a framework
    # (LangChain/LangGraph) — see Step 5b for hand-written tool loops.
    result = my_agent.run(user_input)
    return result
可用 kwargs:
agent_id
、
task_run_id
、
trace_id
、
user_id
、
session_id
。没有
metadata=
kwargs——应通过上述显式 kwargs 附加归因信息。
对于 HTTP handler(FastAPI/Flask),包裹 handler 主体:
python
@app.post("/chat")
async def chat(req: ChatRequest):
    with agenthog.start_task_run(user_id=req.user_id):
        return await my_agent.run(req.message)

TypeScript — callback

TypeScript——回调

ts
import { startTaskRun } from "agenthog";

app.post("/chat", async (req, res) => {
  await startTaskRun({ userId: req.body.userId }, async () => {
    const out = await myAgent.run(req.body.message);
    res.json(out);
  });
});
Available
StartTaskRunArgs
fields:
agentId
,
taskRunId
,
traceId
,
userId
,
sessionId
. No
metadata
field.
If the user's framework has a middleware concept (Express, Hono, FastAPI middleware), prefer wiring
start_task_run
as a middleware so every request gets a task_run automatically.
ts
import { startTaskRun } from "agenthog";

app.post("/chat", async (req, res) => {
  await startTaskRun({ userId: req.body.userId }, async () => {
    const out = await myAgent.run(req.body.message);
    res.json(out);
  });
});
可用的
StartTaskRunArgs
字段:
agentId
、
taskRunId
、
traceId
、
userId
、
sessionId
。没有
metadata
字段。
如果用户使用的框架支持 middleware 概念(Express、Hono、FastAPI middleware),优先将
start_task_run
接入 middleware,使每个请求都自动获得一个
task_run
。

5b. Instrument the agent's tools (the full execution tree)

5b. 为 Agent 的工具埋点(构建完整执行树)

autoinstrument()
captures LLM calls (vendor SDKs + raw-HTTP OpenAI-compatible calls) — but not the agent's tools: ordinary functions that hit an API, query a DB, geocode, run a computation. Left alone, the trace shows only the LLM step, and evals that look for tool usage wrongly report "the agent never used a tool / hallucinated." This is the same boundary in every tracer — Arize/LangSmith auto-trace the full tree only on instrumented frameworks; for hand-written tools they require an annotation too.
This step is what produces the full workflow tree (tool calls + LLM call), not just the model step. Do it whenever the agent has tool/helper functions.
autoinstrument()
会捕获 LLM 调用(厂商 SDK + 原始 HTTP OpenAI 兼容调用),但不会捕获 Agent 的工具:即调用 API、查询数据库、执行地理编码或计算的普通函数。如果不做处理,trace 中只会显示 LLM 步骤,而检查工具使用情况的评估会错误地报告“Agent 从未使用工具/产生了幻觉”。每个 tracer 都存在同样的边界——Arize/LangSmith 只有在已埋点的框架上才能自动追踪完整执行树;对于手写工具,它们同样要求添加注解。
此步骤用于生成包含工具调用和 LLM 调用的完整工作流树,而不只是模型步骤。只要 Agent 拥有工具或辅助函数,就应执行此步骤。

Preferred — one call over the tools module (Python,
agenthog >= 0.9.0
)

首选——通过一次调用覆盖整个工具模块(Python,
agenthog >= 0.9.0
)

Point
instrument_module
at the module holding the agent's tool functions. It wraps every public function defined there as an
agent.tool_call
step in a single call — so no tool can be silently missed the way per-function decorating can. It returns the list of wrapped names; keep that list for the Step 7 count check.
python
import agenthog
import weather            # the module with the agent's tool functions

agenthog.init(...)
wrapped = agenthog.instrument_module(weather)
将
instrument_module
指向存放 Agent 工具函数的模块。它通过一次调用,将该模块中定义的每个公共函数包装为
agent.tool_call
步骤——从而避免逐函数装饰时可能静默遗漏工具。它会返回已包装函数名的列表;请保留该列表,用于步骤 7 的数量检查。
python
import agenthog
import weather            # the module with the agent's tool functions

agenthog.init(...)
wrapped = agenthog.instrument_module(weather)

wrapped == ['get_weather', 'get_air_quality', 'geocode']

wrapped == ['get_weather', 'get_air_quality', 'geocode']


It skips private helpers (leading `_`), imported names, classes, and constants.
Tune the selection when the defaults don't fit:

- A public function that isn't a tool → `instrument_module(weather, exclude=["build_prompt"])`.
- A tool named with a leading `_`, or one that lives among imports → `instrument_module(weather, include=["_geocode"])`.

Functions you already decorated with `@agenthog.tool` are detected and **not
double-wrapped**. **Enumerate the agent's tool module(s) and pass each through
one `instrument_module` call — this is what makes "all tools captured"
structural rather than a per-function judgment you can under-apply.**

它会跳过私有辅助函数(名称以 `_` 开头)、导入的名称、类及常量。默认规则不适用时,可调整选择范围:

- 某个公共函数并非工具 → `instrument_module(weather, exclude=["build_prompt"])`。
- 某个工具名称以 `_` 开头,或位于导入项之中 → `instrument_module(weather, include=["_geocode"])`。

已使用 `@agenthog.tool` 装饰的函数会被识别,且**不会重复包装**。**枚举 Agent 使用的所有工具模块,并为每个模块调用一次 `instrument_module`**——这样,“捕获所有工具”由结构保证,而不是依赖可能应用不充分的逐函数判断。

When tools are spread across many files, or you want per-function control — decorate each

工具分散在多个文件中,或需要逐函数控制时——分别装饰

Add
@agenthog.tool
to each function the agent uses as a tool. One line each; captures args →
tool.input
, return →
tool.output
, plus duration / status / error, as an
agent.tool_call
step under the active
task_run
. Works on sync and async functions; safe to leave in place before
init()
. Decorate every tool — a missed one is silently absent from the trace (exactly what
instrument_module
prevents).
python
import agenthog

@agenthog.tool
def get_weather(city: str) -> dict | None:
    ...

@agenthog.tool(name="geocode")          # custom step name
def _geocode(city: str) -> tuple[float, float] | None:
    ...
TypeScript has no
@tool
decorator or
instrument_module
yet
(JS SDK is pre-
0.6.0
; bulk capture, the decorator, raw-HTTP capture, and auto-flush-on-exit are Python-only for now). For Node/TS agents, instrument tools with the explicit
logToolCall
path in the Alternative section below, and be aware the rest of the auto-capture story is thinner than Python until the JS SDK catches up.
Identify the tool functions — typically the helpers the entrypoint calls before/around the LLM call (data fetches, lookups, actions). Either path should produce a multi-step trace like
task_run → get_weather → geocode → get_air_quality → llm_call
.
为 Agent 使用的每个工具函数添加
@agenthog.tool
。每个函数只需一行;它会将参数捕获为
tool.input
、返回值捕获为
tool.output
,并记录 duration/status/error,作为当前
task_run
下的
agent.tool_call
步骤。适用于同步及异步函数;即使保留在
init()
之前使用也安全。请装饰每一个工具——遗漏的工具不会出现在 trace 中,而这正是
instrument_module
所能防止的问题。
python
import agenthog

@agenthog.tool
def get_weather(city: str) -> dict | None:
    ...

@agenthog.tool(name="geocode")          # custom step name
def _geocode(city: str) -> tuple[float, float] | None:
    ...
TypeScript 目前没有
@tool
装饰器,也没有
instrument_module
(JS SDK 仍处于 0.6.0 之前版本);批量捕获、装饰器、原始 HTTP 捕获及退出时自动 flush 暂时仅支持 Python。对于 Node/TS Agent,应使用下方备选方案中的显式
logToolCall
路径,并注意在 JS SDK 追上 Python SDK 之前,其自动捕获能力较为有限。
识别工具函数——通常就是入口点在 LLM 调用之前或周围调用的辅助函数(数据获取、查询、操作等)。无论采用哪种方式,都应生成类似
task_run → get_weather → geocode → get_air_quality → llm_call
的多步骤 trace。

Alternative — log explicitly (older SDKs, or a raw tool-calling loop)

备选——显式记录(适用于旧版 SDK 或原始工具调用循环)

If you can't decorate (e.g. tools dispatched dynamically in a model tool-calling loop, or the TS SDK which has neither
instrument_module
nor
@tool
), log each call:
python
result = run_tool(name, **args)
agenthog.get_default_client().log_tool_call(name=name, input=args, output=result)
ts
const result = await runTool(name, args);
await getDefaultClient()!.logToolCall({ name, input: args, output: result });
log_tool_call
/
logToolCall
take
name
plus optional
input
,
output
,
status
,
duration_ms
,
error
. Skip tool instrumentation only when every tool already runs through an auto-instrumented framework.
如果无法使用装饰器(例如工具在模型工具调用循环中动态调度,或者使用既没有
instrument_module
也没有
@tool
的 TS SDK),请记录每次调用:
python
result = run_tool(name, **args)
agenthog.get_default_client().log_tool_call(name=name, input=args, output=result)
ts
const result = await runTool(name, args);
await getDefaultClient()!.logToolCall({ name, input: args, output: result });
log_tool_call
/
logToolCall
接受
name
,以及可选的
input
、
output
、
status
、
duration_ms
、
error
。仅当所有工具都已通过自动埋点框架执行时,才可以跳过工具埋点。

6. Document the config (placeholders only — never the real key)

6. 记录配置(仅使用占位符——绝不包含真实密钥)

Add three placeholder lines to
.env.example
(or create it). This file is committed, so it must never contain a real key:
AGENTOS_API_KEY=agops_replace_me
AGENTOS_WORKSPACE_ID=ws_replace_me
AGENTOS_ENDPOINT=https://api.theagentos.space
For the real values:
  • Python (used
    agenthog init
    in Step 2):
    the gitignored
    .env
    is already written and ignored — nothing more to do here except the committed
    .env.example
    placeholders above (for teammates).
  • Otherwise: tell the user to set the real values themselves — in their shell environment, secret manager, or a gitignored
    .env
    . Do not write the plaintext key to any file on their behalf. If they use a
    .env
    , confirm it's listed in
    .gitignore
    (add it if missing) so the secret can't be committed.
向
.env.example
添加三行占位符(如果文件不存在则创建)。该文件会提交到版本库,因此绝不能包含真实密钥:
AGENTOS_API_KEY=agops_replace_me
AGENTOS_WORKSPACE_ID=ws_replace_me
AGENTOS_ENDPOINT=https://api.theagentos.space
对于真实值:
  • **Python(在步骤 2 中使用了
    agenthog init
    ):**被 gitignore 的
    .env
    已经写入并处于忽略状态——除添加供团队成员参考的
    .env.example
    占位符外,无需其他操作。
  • **其他情况:**告知用户自行设置真实值——可放在 shell 环境、密钥管理器或被 gitignore 的
    .env
    中。不要代替用户将明文密钥写入任何文件。如果用户使用
    .env
    ,请确认它已列在
    .gitignore
    中(如缺失则添加),以防止机密被提交。

Make the
.env
actually load (do not skip)

确保
.env
真正加载(不得跳过)

A
.env
file does not populate
os.environ
/
process.env
on its own. The SDK reads the keys from the environment at runtime (Step 4), so if the app doesn't load
.env
the user will set everything correctly and still see no trace with an empty/missing key. Wire the load step to match the runtime:
RuntimeHow
.env
reaches the environment
Next.jsAutomatic — Next loads
.env
/
.env.local
. Nothing to add.
Node (non-Next)Run with
node --env-file=.env …
(Node 20+), or add
import "dotenv/config";
as the first import.
Python — FastAPI / Flask / scriptAdd
from dotenv import load_dotenv; load_dotenv()
before
agenthog.init(...)
(add the
python-dotenv
dep), or use
pydantic-settings
, or run via
uv run --env-file .env …
.
Any runtimeOr just export in the shell before launching:
export AGENTOS_API_KEY=… AGENTOS_WORKSPACE_ID=…
.
Pick the one matching the project. If you add
load_dotenv()
, place it at the top of the entrypoint, before
init
runs. Confirm the var is actually populated (Step 7's "Confirm
AGENTOS_API_KEY
is loaded" check) before declaring done.
.env
文件本身不会自动填充
os.environ
/
process.env
。SDK 会在运行时从环境变量读取这些键(步骤 4),因此,如果应用未加载
.env
,即使用户正确设置所有值,也仍会因密钥为空或缺失而看不到 trace。请根据运行时接入加载步骤:
运行时
.env
进入环境变量的方式
Next.js自动加载——Next.js 会加载
.env
/
.env.local
,无需添加任何内容。
Node(非 Next.js)使用
node --env-file=.env …
运行(Node 20+),或将
import "dotenv/config";
放在首个 import。
Python——FastAPI / Flask / 脚本在
agenthog.init(...)
之前添加
from dotenv import load_dotenv; load_dotenv()
(并添加
python-dotenv
依赖),或使用
pydantic-settings
,或通过
uv run --env-file .env …
运行。
任意运行时也可以在启动前通过 shell 设置:
export AGENTOS_API_KEY=… AGENTOS_WORKSPACE_ID=…
。
选择与项目匹配的方案。如果添加
load_dotenv()
,应将其放在入口点顶部,并确保在
init
运行前执行。在声明完成前,确认变量已实际填充(步骤 7 中的“确认
AGENTOS_API_KEY
已加载”检查)。

7. Verify (hard gate — do not skip, do not assume)

7. 验证(硬性关卡——不得跳过或主观假定)

This step is mandatory and blocking. Setup is not done until you have seen a real trace from a real run. Wiring
init
+
start_task_run
does not by itself produce a trace: if no LLM/tool call is captured, the trace is an empty
task_run
and nothing useful appears. Never report success because the code "looks wired up" — only because you observed the trace.
Check the trace is complete, not just present. It should contain the LLM call and a
tool_call
step for each tool the agent used (Step 5b). Count them: the number of distinct
tool_call
steps must equal the number of tools instrumented — the length of the list
instrument_module
returned, or the number of functions you decorated with
@agenthog.tool
. Fewer means a tool was missed (or an execution path didn't run it); a trace with only the
llm_call
and no tool steps means the tools weren't instrumented at all — go back to Step 5b. Do not pass this gate on a count mismatch. The goal is the full execution tree, the way Arize/LangSmith show it.
Run the app. Exercise one request that hits the wrapped handler. Then verify via one of these paths, in order of simplicity:
此步骤为强制要求,并且是阻塞项。在看到一次真实运行产生的真实 trace 之前,设置尚未完成。仅接入
init
+
start_task_run
本身并不会产生 trace:如果未捕获任何 LLM 或工具调用,trace 就会是一个空的
task_run
,其中没有任何有用信息。绝不能仅因为代码“看起来已经接入”就报告成功——只有实际观察到 trace 后才可以。
**检查 trace 是否完整,而不只是检查它是否存在。**trace 应包含 LLM 调用,并为 Agent 使用的每个工具包含一个
tool_call
步骤(步骤 5b)。进行计数:不同
tool_call
步骤的数量必须等于已埋点的工具数量——即
instrument_module
返回的列表长度,或使用
@agenthog.tool
装饰的函数数量。数量减少意味着遗漏了某个工具(或某条执行路径未运行它);如果 trace 只有
llm_call
而没有工具步骤,则说明根本没有为工具埋点——请返回步骤 5b。数量不匹配时不得通过此关卡。目标是生成完整执行树,就像 Arize/LangSmith 所展示的那样。
运行应用。发起一次会命中已包裹 handler 的请求。然后按以下路径之一进行验证,并优先选择最简单的路径:

Path A — Dashboard (always works)

路径 A——Dashboard(始终可用)

Open in a browser:
https://app.theagentos.space/traces
Sign in if needed. A trace from the request you just exercised should appear within a few seconds. Use this path by default.
在浏览器中打开:
https://app.theagentos.space/traces
如有必要,请登录。刚刚触发的请求所产生的 trace 应在数秒内出现。默认使用此路径。

Path B — CLI verifier (offline, cryptographic)

路径 B——CLI 验证器(离线、加密验证)

The
agenthog
CLI ships as an installed entrypoint, NOT as
python -m agenthog
. There is no
__main__.py
. Invoke the entrypoint directly:
bash
undefined
agenthog
CLI 以已安装的 entrypoint 形式提供,而不是通过
python -m agenthog
运行。它没有
__main__.py
。请直接调用该 entrypoint:
bash
undefined

If agenthog[audit] is installed in the active env:

If agenthog[audit] is installed in the active env:

agenthog audit verify --workspace-id $AGENTOS_WORKSPACE_ID
agenthog audit verify --workspace-id $AGENTOS_WORKSPACE_ID

Or, ephemerally without modifying the project's deps:

Or, ephemerally without modifying the project's deps:

uvx --with 'agenthog[audit]' agenthog audit verify --workspace-id $AGENTOS_WORKSPACE_ID
uvx --with 'agenthog[audit]' agenthog audit verify --workspace-id $AGENTOS_WORKSPACE_ID

Or, with uv run from outside any project (mirrors
uv run --no-project
):

Or, with uv run from outside any project (mirrors
uv run --no-project
):

uv run --no-project --with 'agenthog[audit]' agenthog audit verify
--workspace-id $AGENTOS_WORKSPACE_ID

**Do not** run `python -m agenthog audit verify` — that fails with
`'agenthog' is a package and cannot be directly executed`. The CLI is
invoked via the `agenthog` console-script entrypoint, not the module
runner.

Note: `agenthog audit verify` requires the `[audit]` extra (pulls in
`cryptography` for Ed25519 verification). If you only installed
`agenthog[openai]` for tracing, add `[audit]` for verification or use
Path A.
uv run --no-project --with 'agenthog[audit]' agenthog audit verify
--workspace-id $AGENTOS_WORKSPACE_ID

**不要**运行 `python -m agenthog audit verify`——它会因提示 `'agenthog' is a package and cannot be directly executed'` 而失败。CLI 应通过 `agenthog` console-script entrypoint 调用,而不是 module runner。

注意:`agenthog audit verify` 需要 `[audit]` extra(会引入 `cryptography` 以进行 Ed25519 验证)。如果只为追踪安装了 `agenthog[openai]`,请添加 `[audit]` 用于验证,或者改用路径 A。

If no trace appears after 30 seconds

如果 30 秒后仍没有 trace

  1. Check the app's stdout for
    [agenthog.sdk]
    warning lines.
  2. Confirm
    AGENTOS_API_KEY
    is loaded (not empty, not the placeholder).
  3. Confirm the endpoint is reachable:
    curl -I $AGENTOS_ENDPOINT
    .
  4. Confirm the app actually called
    init
    before the handler runs (sometimes
    init
    is wired after the handler import — fix the import order so
    init
    runs first at module load).
  5. Trace appears but is empty (no LLM step)? The model call wasn't captured.
    autoinstrument()
    covers the vendor SDKs and — on agenthog >= 0.6.0 — raw-HTTP OpenAI-compatible
    /chat/completions
    calls. A custom/non-OpenAI-shaped endpoint won't be auto-traced: log it with
    agenthog.emit("agent.llm_call", {...})
    . (On older SDKs, raw
    requests
    /
    httpx
    calls are never captured — upgrade to >= 0.6.0 or switch to the OpenAI SDK with a custom
    base_url
    .)
  6. Short-lived script and nothing arrives? On agenthog >= 0.6.0 the buffer flushes on exit automatically; on older versions add
    agenthog.flush()
    before the process exits, or upgrade.
  1. 检查应用的标准输出中是否有
    [agenthog.sdk]
    警告。
  2. 确认
    AGENTOS_API_KEY
    已加载,而不是空值或占位符。
  3. 确认 endpoint 可以访问:
    curl -I $AGENTOS_ENDPOINT
    。
  4. 确认应用确实在 handler 运行前调用了
    init
    (有时
    init
    会被接在 handler import 之后——应调整 import 顺序,确保模块加载时首先执行
    init
    )。
  5. **trace 已出现但为空(没有 LLM 步骤)?**说明模型调用未被捕获。
    autoinstrument()
    覆盖厂商 SDK,以及
    agenthog >= 0.6.0
    中的原始 HTTP OpenAI 兼容
    /chat/completions
    调用。自定义或非 OpenAI 格式的 endpoint 不会被自动追踪:应使用
    agenthog.emit("agent.llm_call", {...})
    记录。(在旧版 SDK 中,原始
    requests
    /
    httpx
    调用永远不会被捕获——请升级到 >= 0.6.0,或改用带自定义
    base_url
    的 OpenAI SDK。)
  6. **短生命周期脚本且没有任何数据到达?**在
    agenthog >= 0.6.0
    中,缓冲区会在退出时自动 flush;在旧版本中,应在进程退出前添加
    agenthog.flush()
    ,或进行升级。

8. Report back

8. 汇报结果

Once a trace is verified visible, tell the user:
  • What you installed (which extras)
  • Where you put the
    init
    call (file + line)
  • Where you wrapped the loop (file + line)
  • The trace_id of your verification trace (so they can open it directly)
确认 trace 已可见后,告知用户:
  • 安装了什么(包含哪些 extras)
  • init
    调用放在哪里(文件 + 行号)
  • 循环包装在哪里(文件 + 行号)
  • 验证 trace 的 trace_id(便于用户直接打开)

Rules

规则

  • Never throw. The user's agent must keep running even if AgentHog is misconfigured. The SDK guarantees its own calls don't raise; your wiring should match that contract.
  • Credentials stay in the environment. The API key is read from an env var at runtime. Never hardcode it, never print or echo it, never write the plaintext value to a file, and never scan the filesystem for it. Wire the code to the env var and let the user place the secret (Step 2).
  • Don't auto-instrument secrets. If the user has prompts containing PII or API keys, mention the privacy controls (
    capture_content=False
    ) in the report — don't change the default silently.
  • Don't refactor unrelated code. Only touch what's necessary to wire tracing. If the user wants broader observability work, let them ask explicitly.
  • Use uv if it's already in the project. Otherwise use whatever package manager the project already uses. Don't introduce a new one.
  • **绝不抛出异常。**即使 AgentHog 配置错误,用户的 Agent 也必须继续运行。SDK 保证其内部调用不会抛出异常;你的接入方式应遵守这一约定。
  • **凭据始终保留在环境中。**API key 在运行时从环境变量读取。绝不硬编码、打印或回显,也绝不将明文值写入文件,更不能扫描文件系统来查找它。接入代码以引用环境变量,并让用户放置机密值(步骤 2)。
  • **不要自动埋点机密信息。**如果用户的 prompt 包含 PII 或 API key,请在报告中提及隐私控制项(
    capture_content=False
    )——不要在未说明的情况下静默更改默认值。
  • **不要重构无关代码。**只修改接入追踪所必需的内容。如果用户需要更广泛的可观测性工作,应请用户明确提出。
  • **如果项目中已经使用
    uv
    ,继续使用
    uv
    。**否则使用项目当前采用的包管理器。不要引入新的包管理器。