agenthog-setup
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAgenthog 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, orsetup.pyfiles.*.py - TypeScript / Node if you see with
package.jsonor TypeScript files, or"type": "module".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
belongs and where the per-request loop is.
init查看项目根目录,以确定语言和主要框架:
- Python:如果看到 、
pyproject.toml、requirements.txt或setup.py文件。*.py - TypeScript / Node:如果看到带 的
"type": "module"、TypeScript 文件或package.json。tsconfig.json
如果两者都有,默认使用主要入口点所采用的运行时。仅当确实存在歧义时才询问用户。
识别主要框架:FastAPI、Flask、Django、LangGraph、LangChain、Express、Vercel AI SDK、Next.js、Hono 等。框架决定 的位置以及每次请求循环所在的位置。
init2. 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_KEYAGENTOS_WORKSPACE_ID必需项:AGENTOS_API_KEY
和 AGENTOS_WORKSPACE_ID
AGENTOS_API_KEYAGENTOS_WORKSPACE_IDThese are secrets, resolved at runtime from the environment — the SDK reads
/ from env vars (see the
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.
AGENTOS_API_KEYAGENTOS_WORKSPACE_IDinit-
Already in the environment? (,
AGENTOS_API_KEYset) — good, nothing to gather. Wire the code to read them and move on.AGENTOS_WORKSPACE_ID -
Not set? The user provides them — you never handle the secret. Offer two ways and prefer the first. A bareis 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):
export-
Preferred —(
agenthog init): prompts for both values, writes a gitignoredagenthog >= 0.5.0(.env), and persists across restarts and across shells. The user runs it and types the key; you do not. Because it writes0600, the values survive new terminals — no two-shells mismatch..env -
Fallback — shell(ephemeral, fine for a quick one-off): the user sets the values in the terminal where they'll run the app:
exportbashexport AGENTOS_API_KEY=<their key> export AGENTOS_WORKSPACE_ID=<their workspace id>The quickstart page gives a ready-to-pasteblock. This lasts only for that shell session — recommendexportfor anything persistent.agenthog init
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 or echoing the key into your context:
cat .envbash
undefined这些是机密信息,在运行时从环境变量解析——SDK 会从环境变量读取 / (参见下面的 示例)。你的工作是将代码接入这些环境变量并确认变量已存在——绝不获取、查看或自行保存机密值。
AGENTOS_API_KEYAGENTOS_WORKSPACE_IDinit-
环境中已存在?(已设置、
AGENTOS_API_KEY)——很好,无需收集任何内容。将代码接入并读取这些变量,然后继续。AGENTOS_WORKSPACE_ID -
尚未设置?由用户提供——你绝不处理机密值。提供两种方式,并优先使用第一种。直接使用仅对当前 shell 有效,终端关闭后就会失效——这是“只追踪了一次,然后停止”的常见原因,而且该问题对其他 shell(包括你自己的工具 shell)不可见:
export-
首选——(
agenthog init):会提示用户输入两个值,将凭据写入被 gitignore 的agenthog >= 0.5.0(权限为.env),并在重启及不同 shell 之间持续生效。由用户运行并输入密钥;你不能代替用户输入。由于它会写入0600,这些值可跨新终端保留,不会出现两个 shell 配置不一致的问题。.env -
备选——shell(临时方案,适合快速一次性使用):用户在运行应用的终端中设置这些值:
exportbashexport AGENTOS_API_KEY=<their key> export AGENTOS_WORKSPACE_ID=<their workspace id>快速入门页面提供了一个可直接粘贴的代码块。该配置仅在当前 shell 会话中有效——任何需要持久生效的场景都应推荐使用export。agenthog init
用户可从 https://app.theagentos.space 获取这些值(API key:Settings → API Keys;workspace ID:侧边栏 chip / 右上角)。用户完成其中一种配置后,按变量名确认其存在(见下文),然后继续。 -
确认变量存在,但绝不读取机密值:
检查变量是否已设置,而不是读取其值——只做布尔存在性测试,绝不执行 ,也绝不将密钥回显到上下文中:
cat .envbash
undefinedprints 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- If is already set in the environment, use that.
AGENTOS_ENDPOINT - 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
placeholder).
.env.exampleAGENTOS_ENDPOINT- 如果环境中已设置 ,则使用该值。
AGENTOS_ENDPOINT - 否则使用默认值:。
https://api.theagentos.space
仅当有明确证据表明用户希望覆盖默认值时,才询问 Endpoint——例如用户表示“我要自托管”或“我们在自己的基础设施上运行 agenthog”。
否则,直接选择默认值并继续。对于 95% 使用托管云的用户,每次快速入门都询问 Endpoint 会造成不必要的摩擦。
绝不提交明文 API key,也绝不自行将其写入磁盘——真实值由用户放置(步骤 6 负责接入代码并提供 占位符)。
.env.example3. Install the SDK (a new-enough version is mandatory)
3. 安装 SDK(必须使用足够新的版本)
Minimum supported version: Python, TypeScriptagenthog >= 0.9.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 >= 0.3.0credentials (0.5.0), raw-HTTP LLM capture for OpenAI-compatible endpoints + automatic flush-on-exit (0.6.0), theagenthog init/@agenthog.tooldecorator for tracing the agent's tools (0.7.0), and one-call tool capture@traceable(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).instrument_module
Install (or upgrade) 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.
agenthog最低支持版本:Python,TypeScriptagenthog >= 0.9.0。 摄取 API 会拒绝旧版 SDK 发送的事件(HTTP 426)。Python 最低版本为 0.9.0,因为此 skill 的完整功能依赖其特性:凭据初始化agenthog >= 0.3.0(0.5.0)、面向 OpenAI 兼容端点的原始 HTTP LLM 捕获及退出时自动 flush(0.6.0)、用于追踪 Agent 工具的agenthog init/@agenthog.tool装饰器(0.7.0),以及一次调用即可完成工具捕获的@traceable(步骤 5b,0.9.0)——这可确保不会静默遗漏任何工具。低于最低版本时,设置只会生成不完整的 trace(缺少工具步骤,或者短生命周期进程完全没有 trace)。instrument_module
作为设置的一部分安装(或升级),并使用项目现有的包管理器——即当前负责管理项目依赖的同一个工具。告知用户新增了哪些依赖,并锁定最低版本,确保已有的旧版本被升级,而不是继续保留。如果无法确定包管理器,应先询问用户再安装。
agenthogPython
Python
Detect the package manager (, , , ) and install with the
version floor + upgrade:
uvpoetrypippipenvbash
undefined检测包管理器(、、、),使用带版本下限及升级选项的命令安装:
uvpoetrypippipenvbash
undefineduv (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:
```bashpip install -U 'agenthog>=0.9.0'
对于具备一等自动埋点支持的框架,安装相应的 extras:
```bashOpenAI 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'
undefineduv add 'agenthog[otel]>=0.9.0'
undefinedTypeScript
TypeScript
bash
undefinedbash
undefinedpnpm (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 , TypeScript ).
If it isn't, upgrade and re-check before continuing — the rest of the setup (and
the ingestion API) assumes it.
>= 0.9.0>= 0.3.0bash
undefined安装后,确认版本符合要求(Python ,TypeScript )。如果不符合,应先升级并重新检查,再继续——后续设置及摄取 API 都依赖此版本。
>= 0.9.0>= 0.3.0bash
undefinedPython — 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)"
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)"
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)"
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)"
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
init4. 在应用启动时接入 init
initThe call must run once, before any LLM/tool call you want traced.
Place it in the app's primary entrypoint:
init| Framework | Where to call init |
|---|---|
| FastAPI | |
| Flask | |
| Django | |
| LangGraph script | top of the script, before graph construction |
| Express | |
| Next.js | |
| Vercel AI SDK | wherever the AI client is constructed |
init| 框架 | |
|---|---|
| FastAPI | |
| Flask | |
| Django | |
| LangGraph 脚本 | 脚本顶部,位于构建 graph 之前 |
| Express | |
| Next.js | |
| 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
requestshttpx/chat/completions endpoints made via requests
or httpx
— so agents that
requestshttpxPOST 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 that describes what the service does, not just the repo
name. Examples: , , .
agentIdcustomer-support-botcode-review-agentetl-pipelinets
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";选择一个能够描述服务用途的 ,而不要只使用仓库名称。例如:、、。
agentIdcustomer-support-botcode-review-agentetl-pipeline5. Wrap the primary agent loop in start_task_run
start_task_run5. 使用 start_task_run
包裹主要 Agent 循环
start_task_runOne = 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 都会嵌套在其中。
task_runPython — 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 resultAvailable kwargs: , , , ,
. There is no kwarg — attach attribution via
the explicit kwargs above instead.
agent_idtask_run_idtrace_iduser_idsession_idmetadata=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:、、、、。没有 kwargs——应通过上述显式 kwargs 附加归因信息。
agent_idtask_run_idtrace_iduser_idsession_idmetadata=对于 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 fields: , , ,
, . No field.
StartTaskRunArgsagentIdtaskRunIdtraceIduserIdsessionIdmetadataIf the user's framework has a middleware concept (Express, Hono, FastAPI
middleware), prefer wiring as a middleware so every request
gets a task_run automatically.
start_task_runts
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);
});
});可用的 字段:、、、、。没有 字段。
StartTaskRunArgsagentIdtaskRunIdtraceIduserIdsessionIdmetadata如果用户使用的框架支持 middleware 概念(Express、Hono、FastAPI middleware),优先将 接入 middleware,使每个请求都自动获得一个 。
start_task_runtask_run5b. Instrument the agent's tools (the full execution tree)
5b. 为 Agent 的工具埋点(构建完整执行树)
autoinstrument()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 调用的完整工作流树,而不只是模型步骤。只要 Agent 拥有工具或辅助函数,就应执行此步骤。
Preferred — one call over the tools module (Python, agenthog >= 0.9.0
)
agenthog >= 0.9.0首选——通过一次调用覆盖整个工具模块(Python,agenthog >= 0.9.0
)
agenthog >= 0.9.0Point at the module holding the agent's tool functions. It
wraps every public function defined there as an 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.
instrument_moduleagent.tool_callpython
import agenthog
import weather # the module with the agent's tool functions
agenthog.init(...)
wrapped = agenthog.instrument_module(weather)将 指向存放 Agent 工具函数的模块。它通过一次调用,将该模块中定义的每个公共函数包装为 步骤——从而避免逐函数装饰时可能静默遗漏工具。它会返回已包装函数名的列表;请保留该列表,用于步骤 7 的数量检查。
instrument_moduleagent.tool_callpython
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 to each function the agent uses as a tool. One line each;
captures args → , return → , plus duration / status /
error, as an step under the active . Works on sync
and async functions; safe to leave in place before . Decorate every
tool — a missed one is silently absent from the trace (exactly what
prevents).
@agenthog.tooltool.inputtool.outputagent.tool_calltask_runinit()instrument_modulepython
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 nodecorator or@toolyet (JS SDK is pre-instrument_module; 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 explicit0.6.0path 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.logToolCall
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 使用的每个工具函数添加 。每个函数只需一行;它会将参数捕获为 、返回值捕获为 ,并记录 duration/status/error,作为当前 下的 步骤。适用于同步及异步函数;即使保留在 之前使用也安全。请装饰每一个工具——遗漏的工具不会出现在 trace 中,而这正是 所能防止的问题。
@agenthog.tooltool.inputtool.outputtask_runagent.tool_callinit()instrument_modulepython
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(JS SDK 仍处于 0.6.0 之前版本);批量捕获、装饰器、原始 HTTP 捕获及退出时自动 flush 暂时仅支持 Python。对于 Node/TS Agent,应使用下方备选方案中的显式instrument_module路径,并注意在 JS SDK 追上 Python SDK 之前,其自动捕获能力较为有限。logToolCall
识别工具函数——通常就是入口点在 LLM 调用之前或周围调用的辅助函数(数据获取、查询、操作等)。无论采用哪种方式,都应生成类似 的多步骤 trace。
task_run → get_weather → geocode → get_air_quality → llm_callAlternative — 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 nor
), log each call:
instrument_module@toolpython
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_calllogToolCallnameinputoutputstatusduration_mserror如果无法使用装饰器(例如工具在模型工具调用循环中动态调度,或者使用既没有 也没有 的 TS SDK),请记录每次调用:
instrument_module@toolpython
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_calllogToolCallnameinputoutputstatusduration_mserror6. Document the config (placeholders only — never the real key)
6. 记录配置(仅使用占位符——绝不包含真实密钥)
Add three placeholder lines to (or create it). This file is
committed, so it must never contain a real key:
.env.exampleAGENTOS_API_KEY=agops_replace_me
AGENTOS_WORKSPACE_ID=ws_replace_me
AGENTOS_ENDPOINT=https://api.theagentos.spaceFor the real values:
- Python (used in Step 2): the gitignored
agenthog initis already written and ignored — nothing more to do here except the committed.envplaceholders above (for teammates)..env.example - Otherwise: tell the user to set the real values themselves — in their
shell environment, secret manager, or a gitignored . Do not write the plaintext key to any file on their behalf. If they use a
.env, confirm it's listed in.env(add it if missing) so the secret can't be committed..gitignore
向 添加三行占位符(如果文件不存在则创建)。该文件会提交到版本库,因此绝不能包含真实密钥:
.env.exampleAGENTOS_API_KEY=agops_replace_me
AGENTOS_WORKSPACE_ID=ws_replace_me
AGENTOS_ENDPOINT=https://api.theagentos.space对于真实值:
- **Python(在步骤 2 中使用了 ):**被 gitignore 的
agenthog init已经写入并处于忽略状态——除添加供团队成员参考的.env占位符外,无需其他操作。.env.example - **其他情况:**告知用户自行设置真实值——可放在 shell 环境、密钥管理器或被 gitignore 的 中。不要代替用户将明文密钥写入任何文件。如果用户使用
.env,请确认它已列在.env中(如缺失则添加),以防止机密被提交。.gitignore
Make the .env
actually load (do not skip)
.env确保 .env
真正加载(不得跳过)
.envA file does not populate / on its own.
The SDK reads the keys from the environment at runtime (Step 4), so if the app
doesn't load the user will set everything correctly and still see no
trace with an empty/missing key. Wire the load step to match the runtime:
.envos.environprocess.env.env| Runtime | How |
|---|---|
| Next.js | Automatic — Next loads |
| Node (non-Next) | Run with |
| Python — FastAPI / Flask / script | Add |
| Any runtime | Or just export in the shell before launching: |
Pick the one matching the project. If you add , place it at the
top of the entrypoint, before runs. Confirm the var is actually populated
(Step 7's "Confirm is loaded" check) before declaring done.
load_dotenv()initAGENTOS_API_KEY.envos.environprocess.env.env| 运行时 | |
|---|---|
| Next.js | 自动加载——Next.js 会加载 |
| Node(非 Next.js) | 使用 |
| Python——FastAPI / Flask / 脚本 | 在 |
| 任意运行时 | 也可以在启动前通过 shell 设置: |
选择与项目匹配的方案。如果添加 ,应将其放在入口点顶部,并确保在 运行前执行。在声明完成前,确认变量已实际填充(步骤 7 中的“确认 已加载”检查)。
load_dotenv()initAGENTOS_API_KEY7. 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 + does not by
itself produce a trace: if no LLM/tool call is captured, the trace is an empty
and nothing useful appears. Never report success because the code
"looks wired up" — only because you observed the trace.
initstart_task_runtask_runCheck the trace is complete, not just present. It should contain the LLM
call and a step for each tool the agent used (Step 5b).
Count them: the number of distinct steps must equal the number
of tools instrumented — the length of the list returned, or
the number of functions you decorated with . Fewer means a tool
was missed (or an execution path didn't run it); a trace with only the
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.
tool_calltool_callinstrument_module@agenthog.toolllm_callRun the app. Exercise one request that hits the wrapped handler. Then
verify via one of these paths, in order of simplicity:
此步骤为强制要求,并且是阻塞项。在看到一次真实运行产生的真实 trace 之前,设置尚未完成。仅接入 + 本身并不会产生 trace:如果未捕获任何 LLM 或工具调用,trace 就会是一个空的 ,其中没有任何有用信息。绝不能仅因为代码“看起来已经接入”就报告成功——只有实际观察到 trace 后才可以。
initstart_task_runtask_run**检查 trace 是否完整,而不只是检查它是否存在。**trace 应包含 LLM 调用,并为 Agent 使用的每个工具包含一个 步骤(步骤 5b)。进行计数:不同 步骤的数量必须等于已埋点的工具数量——即 返回的列表长度,或使用 装饰的函数数量。数量减少意味着遗漏了某个工具(或某条执行路径未运行它);如果 trace 只有 而没有工具步骤,则说明根本没有为工具埋点——请返回步骤 5b。数量不匹配时不得通过此关卡。目标是生成完整执行树,就像 Arize/LangSmith 所展示的那样。
tool_calltool_callinstrument_module@agenthog.toolllm_call运行应用。发起一次会命中已包裹 handler 的请求。然后按以下路径之一进行验证,并优先选择最简单的路径:
Path A — Dashboard (always works)
路径 A——Dashboard(始终可用)
Open in a browser:
https://app.theagentos.space/tracesSign 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 CLI ships as an installed entrypoint, NOT as . There is no . Invoke the entrypoint directly:
agenthogpython -m agenthog__main__.pybash
undefinedagenthogpython -m agenthog__main__.pybash
undefinedIf 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
):
uv run --no-projectOr, with uv run from outside any project (mirrors uv run --no-project
):
uv run --no-projectuv run --no-project --with 'agenthog[audit]' agenthog audit verify
--workspace-id $AGENTOS_WORKSPACE_ID
--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
--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
- Check the app's stdout for warning lines.
[agenthog.sdk] - Confirm is loaded (not empty, not the placeholder).
AGENTOS_API_KEY - Confirm the endpoint is reachable: .
curl -I $AGENTOS_ENDPOINT - Confirm the app actually called before the handler runs (sometimes
initis wired after the handler import — fix the import order soinitruns first at module load).init - Trace appears but is empty (no LLM step)? The model call wasn't
captured. covers the vendor SDKs and — on agenthog >= 0.6.0 — raw-HTTP OpenAI-compatible
autoinstrument()calls. A custom/non-OpenAI-shaped endpoint won't be auto-traced: log it with/chat/completions. (On older SDKs, rawagenthog.emit("agent.llm_call", {...})/requestscalls are never captured — upgrade to >= 0.6.0 or switch to the OpenAI SDK with a customhttpx.)base_url - Short-lived script and nothing arrives? On agenthog >= 0.6.0 the buffer
flushes on exit automatically; on older versions add before the process exits, or upgrade.
agenthog.flush()
- 检查应用的标准输出中是否有 警告。
[agenthog.sdk] - 确认 已加载,而不是空值或占位符。
AGENTOS_API_KEY - 确认 endpoint 可以访问:。
curl -I $AGENTOS_ENDPOINT - 确认应用确实在 handler 运行前调用了 (有时
init会被接在 handler import 之后——应调整 import 顺序,确保模块加载时首先执行init)。init - **trace 已出现但为空(没有 LLM 步骤)?**说明模型调用未被捕获。覆盖厂商 SDK,以及
autoinstrument()中的原始 HTTP OpenAI 兼容agenthog >= 0.6.0调用。自定义或非 OpenAI 格式的 endpoint 不会被自动追踪:应使用/chat/completions记录。(在旧版 SDK 中,原始agenthog.emit("agent.llm_call", {...})/requests调用永远不会被捕获——请升级到 >= 0.6.0,或改用带自定义httpx的 OpenAI SDK。)base_url - **短生命周期脚本且没有任何数据到达?**在 中,缓冲区会在退出时自动 flush;在旧版本中,应在进程退出前添加
agenthog >= 0.6.0,或进行升级。agenthog.flush()
8. Report back
8. 汇报结果
Once a trace is verified visible, tell the user:
- What you installed (which extras)
- Where you put the call (file + line)
init - 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 () in the report — don't change the default silently.
capture_content=False - 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