操作场景
本文介绍如何将部署在腾讯云容器服务 TKE 中的 AI Agent 接入 CLS Agent 可观测,实现会话、调用链、Token 消耗和响应性能的统一观测。
当前已支持接入 Codebuddy、WorkBuddy、DeepSeek Harness、Claude Code、Codex、MiMo Code、OpenClaw、Pi Coding Agent、Hermes Agent、Cursor、OpenCode,后续将持续扩展对更多 AI Agent 的支持。
说明:
本文的 CLS 配置、鉴权、Onesuite-Pilot 部署和上报验证步骤适用于受支持的 AI Agent。由于不同 Agent 的配置文件、启动命令、服务端口、健康检查地址和插件注入方式不同,本文在涉及 Agent 专属配置时以 OpenCode 为例进行介绍。当您使用其他 Agent 时,请根据实际情况调整对应配置。
本文提供以下两种接入方式,您可根据实际情况选择:
方式一:运行期接入。容器启动时安装 Onesuite-Pilot,无需修改现有镜像,适合快速接入和试点。
方式二:镜像接入。建镜像时安装 Onesuite-Pilot,容器启动速度更快,适合规模化生产。
维度 | 运行期接入 | 镜像接入 |
是否修改镜像 | 否 | 是 |
容器启动耗时 | 约90秒 | 秒级 |
版本管理 | 由安装源控制 | 由镜像版本控制 |
运行期公网依赖 | 需要 | 不需要 |
升级方式 | 重启容器 | 重建镜像 |
适用阶段 | 接入与试点 | 规模化生产 |
安全要求
密钥通过 K8s Secret 以环境变量注入,不写入镜像、配置文件或日志。
强鉴权使用最小权限子账号,权限范围限定为单个日志主题的
cls:UploadLog。容器以非 root 用户运行。
不对公网暴露 Agent 的未鉴权接口。本文以 OpenCode 为例,其 HTTP 接口具备命令执行能力,生产环境需设置
OPENCODE_SERVER_PASSWORD,且不通过 Ingress 对外暴露。弱鉴权允许匿名写入,仅在可信网络环境中使用。
前提条件
在安装前,请确认已满足以下条件:
已开通 日志服务 CLS。
AI Agent 已部署在 TKE 集群中。本文示例采用每个用户对应一个 Pod 的部署方式;使用其他部署方式时,请根据业务身份体系配置
userId。TKE 集群的 Kubernetes 版本为 1.24或以上,节点架构为 AMD64。
使用运行期接入时,TKE 节点需能访问 Onesuite-Pilot 安装地址;使用镜像接入时,镜像构建环境需能访问该地址。
容器需以非 root 用户运行,并具备可写的数据目录。
前期配置
步骤1:创建 Agent 可观测应用
1. 进入 日志服务控制台 > Agent 可观测 页面。
2. 单击应用接入,根据页面提示创建应用。
3. 在新创建的应用右侧单击编辑,复制 Trace 日志主题 ID。该 ID 用于后续配置中的
CLS_TOPIC_ID。步骤2:获取 CLS Endpoint
场景 | Endpoint |
TKE 与日志主题同地域(推荐) | <region>.cls.tencentyun.com |
TKE 与日志主题跨地域 | <region>.cls.tencentcs.com |
同地域使用内网 Endpoint,延迟更低且不消耗公网流量。
步骤3:安装 Onesuite-Pilot
Onesuite-Pilot 上报 CLS 支持强鉴权与弱鉴权两种方式,请任选其一。
执行以下一键安装命令。请将参数值替换为您在 CLS 控制台获取的实际信息。
curl -fsSL https://onesuite-pilot-1254077820.cos.ap-shanghai.myqcloud.com/onesuite-pilot/installer.sh | bash -s -- install \\--cls-endpoint "<your-cls-endpoint>" \\--cls-topic-id "<your-topic-id>" \\--cls-secret-id "<your-secret-id>" \\--cls-secret-key "<your-secret-key>"
使用账号 UIN 上报,无需配置密钥,但需进入目标日志主题的基本信息页面,在高级设置中开启匿名上传,并在匿名操作中开启 API/SDK 上传日志。

执行以下一键安装命令。请将参数值替换为您在 CLS 控制台获取的实际信息。
curl -fsSL https://onesuite-pilot-1254077820.cos.ap-shanghai.myqcloud.com/onesuite-pilot/installer.sh | bash -s -- install \\--cls-endpoint "<your-cls-endpoint>" \\--cls-topic-id "<your-topic-id>" \\--cls-uin "<your-account-uin>"
说明:
鉴权优先级:若同时提供了密钥对(SecretId / SecretKey)与 UIN,则以密钥对(强鉴权)为准,UIN 被忽略;仅提供 UIN 时走弱鉴权;两者均未提供时 CLS 上报不会启用。
安装参数说明
参数 | 必填 | 说明 |
--cls-endpoint | 是 | |
--cls-topic-id | 是 | 目标日志主题 ID(TopicId)。 |
--cls-secret-id | 强鉴权时必填 | |
--cls-secret-key | 强鉴权时必填 | |
--cls-uin | 弱鉴权时必填 | 账号 UIN,弱鉴权模式使用,与密钥对(SecretId / SecretKey)二选一,UIN 在配置文件中以明文存储;使用前需进入目标日志主题的基本信息页面,在高级设置中开启匿名上传,并在匿名操作中开启 API/SDK 上传日志。 |
--user-id | 否 | |
--user-name | 否 | 用户展示名,映射为 gen_ai.user.name,与 userId 为两个独立字段。 |
--agent-alias | 否 | 自定义 Agent 名称。配置后,上报日志中的 service.name、gen_ai.agent.type 等 Agent 字段将统一使用该值。 |
--agents | 否 | 指定接入的 Agent 标识列表(逗号分隔),例如 OpenCode 对应 opencode。请填写 Onesuite-Pilot 支持的 Agent 标识,不能统一填写为 agent;不指定时,Onesuite-Pilot 将尝试自动接入当前环境中探测到的受支持 Agent。 |
--data-dir | 否 | 自定义数据目录。 |
--mirror | 否 | npm 依赖下载镜像。国内网络环境建议填 cn(使用 npmmirror 镜像源),可显著提升安装成功率与速度;也可填写自定义镜像地址。填 none 表示不使用镜像。 |
--auto-update | 否 | 自动升级,建议开启。 |
--skip-cls-check | 否 | 跳过安装时的 CLS 连通性与鉴权校验,直接写入配置。仅在无外网连通等特殊场景下使用,一般不建议开启。 |
安装脚本将依次完成:依赖检查 → 下载安装包 → 探测 AI Agent → 部署程序 → 安装 Hook 脚本 → 写入配置 → 注册并启动服务。出现
✅ 安装完成! 即表示部署成功。配置 userId
userId 用于标识 Agent 的业务用户,并写入每个 Span 的 gen_ai.user.id 字段。该字段是 Agent 可观测按用户查询和聚合的主要维度。建议使用稳定且唯一的内部用户标识,避免使用手机号、邮箱等敏感信息。取值优先级
最终生效的
userId 按以下顺序获取:1. 环境变量
ONESUITE_PILOT_USER_ID。2. 安装参数
--user-id 写入的配置项 userId。3. 数据目录下的
user.id 文件。4. 容器主机名(兜底值)。
推荐配置方式
本文示例采用每个用户对应一个 Pod 的部署方式,建议通过环境变量注入业务用户标识:
env:- name: ONESUITE_PILOT_USER_IDvalue: "<USER_ID>"
若用户标识保存在 Kubernetes Secret 中,可按以下方式引用:
env:- name: ONESUITE_PILOT_USER_IDvalueFrom:secretKeyRef:name: user-identitykey: userId
说明:
一个 Pod 服务多个用户时,不要为所有请求配置同一个固定
ONESUITE_PILOT_USER_ID。请根据目标 Agent 的接入方式,在每次 Agent 调用中传递实际业务用户标识。可选:配置用户展示名
通过
ONESUITE_PILOT_USER_NAME 配置用户展示名,该值写入 gen_ai.user.name,仅用于展示,不替代 userId:env:- name: ONESUITE_PILOT_USER_NAMEvalue: "<USER_NAME>"
接入步骤
说明:
以下运行期和镜像接入示例均以 OpenCode 为例。使用其他受支持的 AI Agent 时,CLS 上报参数、Kubernetes Secret 和 Onesuite-Pilot 管理命令保持不变;请将
--agents opencode、OpenCode 配置文件、启动命令、服务端口、健康检查地址和插件验证方式替换为目标 Agent 对应配置。两种方案的整体流程和容器配置原则相同,可平滑切换。以下 Agent 专属配置均以 OpenCode 为例。
方式一:运行期接入
容器启动时完成安装与插件注入,无需修改现有镜像。不同 Agent 的插件注入方式可能不同,下文以 OpenCode 为例进行介绍。
步骤1:确认启动顺序(以 OpenCode 为例)
对于 OpenCode,容器启动脚本需按以下顺序执行:
1. 预置 OpenCode 配置文件
~/.config/opencode/opencode.json。2. 安装 onesuite-pilot:完成插件注入并启动采集进程。
3. 启动 OpenCode 服务。
步骤2:配置 entrypoint.sh
以下脚本中的 OpenCode 配置文件、
--agents opencode 和启动命令均为示例。接入其他 Agent 时,请替换为对应的 Agent 标识、配置文件和启动命令。#!/usr/bin/env bashset -uo pipefaillog() { echo "[entrypoint] $*"; }: "${HOME:=/home/appuser}": "${ONESUITE_PILOT_DATA_DIR:=${HOME}/.onesuite-pilot}"OPENCODE_CONFIG_DIR="${HOME}/.config/opencode"OPENCODE_CONFIG="${OPENCODE_CONFIG_DIR}/opencode.json"PILOT_BIN="${HOME}/.local/bin/onesuite-pilot"INSTALLER_URL="https://onesuite-pilot-1254077820.cos.ap-shanghai.myqcloud.com/onesuite-pilot/installer.sh"# 1) 预置 OpenCode 配置文件mkdir -p "${OPENCODE_CONFIG_DIR}"[ -f "${OPENCODE_CONFIG}" ] || echo '{}' > "${OPENCODE_CONFIG}"# 2) 安装 onesuite-pilotinstall_pilot() {curl -fsSL --retry 3 --max-time 180 -o /tmp/installer.sh "${INSTALLER_URL}"local args=(--cls-endpoint "${ONESUITE_PILOT_CLS_ENDPOINT}"--cls-topic-id "${ONESUITE_PILOT_CLS_TOPIC_ID}"--user-id "${ONESUITE_PILOT_USER_ID}"--data-dir "${ONESUITE_PILOT_DATA_DIR}"# OpenCode 对应 opencode;接入其他 Agent 时替换为相应标识--agents opencode--lang en)[ -n "${ONESUITE_PILOT_USER_NAME:-}" ] && \\args+=(--user-name "${ONESUITE_PILOT_USER_NAME}")if [ -n "${ONESUITE_PILOT_CLS_SECRET_ID:-}" ]; thenargs+=(--cls-secret-id "${ONESUITE_PILOT_CLS_SECRET_ID}")args+=(--cls-secret-key "${ONESUITE_PILOT_CLS_SECRET_KEY}")elseargs+=(--cls-uin "${ONESUITE_PILOT_CLS_UIN}")fibash /tmp/installer.sh install "${args[@]}" 2>&1 | tail -20rm -f /tmp/installer.sh}if [ -x "${PILOT_BIN}" ]; then"${PILOT_BIN}" startelseinstall_pilotfi"${PILOT_BIN}" doctor 2>&1 | tail -10# 3) 退出时刷出采集缓冲区shutdown() {"${PILOT_BIN}" restart >/dev/null 2>&1sleep 3"${PILOT_BIN}" stop >/dev/null 2>&1[ -n "${OPENCODE_PID:-}" ] && kill -TERM "${OPENCODE_PID}" 2>/dev/nullwait 2>/dev/nullexit 0}trap shutdown SIGTERM SIGINT# 4) 启动 OpenCodelog "starting opencode serve"opencode serve --port "${AGENT_PORT:-4096}" --hostname 0.0.0.0 &OPENCODE_PID=$!wait "${OPENCODE_PID}"
将该脚本加入镜像并设为 ENTRYPOINT:
COPY --chown=1000:1000 entrypoint.sh /entrypoint.shRUN chmod +x /entrypoint.shENTRYPOINT ["/entrypoint.sh"]
步骤3:创建 Kubernetes Secret
强鉴权方式执行:
kubectl -n <NAMESPACE> create secret generic cls-credential \\--from-literal=secretId='<CLS_SECRET_ID>' \\--from-literal=secretKey='<CLS_SECRET_KEY>'
弱鉴权方式跳过此步骤。
步骤4:配置 Deployment
以下示例使用 OpenCode 的默认端口
4096 和健康检查地址 /global/health。接入其他 Agent 时,请替换 <AGENT_IMAGE>、<AGENT_PORT>、健康检查地址和 ONESUITE_PILOT_SERVICE_NAME。Onesuite-Pilot 需要向数据目录写入配置、采集位点和缓存数据。
readOnlyRootFilesystem 位于 Deployment 的容器级 spec.template.spec.containers[].securityContext 中,可通过以下方式查看:TKE 控制台:进入目标集群,在工作负载 > Deployment 中选择目标工作负载,单击编辑 YAML,查看对应容器的
securityContext.readOnlyRootFilesystem。kubectl:执行以下命令查看 Deployment YAML,并定位上述字段。
kubectl -n <NAMESPACE> get deployment <DEPLOYMENT_NAME> -o yaml
该字段未配置或设置为
false 时,容器根文件系统可写;设置为 true 时,容器根文件系统只读。本文示例需要在容器启动时安装 Onesuite-Pilot,因此在对应容器的 securityContext 中显式设置 readOnlyRootFilesystem: false。apiVersion: apps/v1kind: Deploymentmetadata:name: ai-agent-<USER_ID>namespace: <NAMESPACE>labels:app: ai-agentuser: "<USER_ID>"spec:replicas: 1selector:matchLabels:app: ai-agentuser: "<USER_ID>"template:metadata:labels:app: ai-agentuser: "<USER_ID>"spec:securityContext:runAsUser: 1000runAsGroup: 1000fsGroup: 1000terminationGracePeriodSeconds: 45containers:- name: ai-agentimage: <AGENT_IMAGE>securityContext:readOnlyRootFilesystem: falseports:- containerPort: <AGENT_PORT>env:- name: HOMEvalue: /home/appuser- name: ONESUITE_PILOT_DATA_DIRvalue: /home/appuser/.onesuite-pilot# 用户标识- name: ONESUITE_PILOT_USER_IDvalue: "<USER_ID>"- name: ONESUITE_PILOT_USER_NAMEvalue: "<USER_NAME>"- name: ONESUITE_PILOT_SERVICE_NAMEvalue: "opencode"- name: AGENT_PORTvalue: "<AGENT_PORT>"# CLS 上报目标- name: ONESUITE_PILOT_CLS_ENDPOINTvalue: "<CLS_ENDPOINT>"- name: ONESUITE_PILOT_CLS_TOPIC_IDvalue: "<CLS_TOPIC_ID>"# 强鉴权- name: ONESUITE_PILOT_CLS_SECRET_IDvalueFrom:secretKeyRef: { name: cls-credential, key: secretId }- name: ONESUITE_PILOT_CLS_SECRET_KEYvalueFrom:secretKeyRef: { name: cls-credential, key: secretKey }# 弱鉴权:删除上面两项,使用下面一项# - name: ONESUITE_PILOT_CLS_UIN# value: "<CLS_UIN>"- name: ONESUITE_PILOT_AUTO_UPDATE_ENABLEDvalue: "false"- name: ONESUITE_PILOT_ENABLE_STATUS_BAR_APPvalue: "false"lifecycle:preStop:exec:command:- /bin/bash- -c- '$HOME/.local/bin/onesuite-pilot restart; sleep 8'readinessProbe:httpGet: { path: /global/health, port: <AGENT_PORT> }initialDelaySeconds: 20periodSeconds: 10failureThreshold: 15volumeMounts:- name: homemountPath: /home/appuserresources:requests: { cpu: 300m, memory: 768Mi }limits: { cpu: "2", memory: 2Gi }volumes:- name: homeemptyDir: {}---apiVersion: v1kind: Servicemetadata:name: ai-agent-<USER_ID>namespace: <NAMESPACE>spec:type: ClusterIPselector:app: ai-agentuser: "<USER_ID>"ports:- port: <AGENT_PORT>targetPort: <AGENT_PORT>
配置说明:
配置 | 说明 |
runAsUser: 1000 | 以非 root 用户运行 |
readOnlyRootFilesystem: false | 允许容器启动时安装 Onesuite-Pilot,并写入数据目录和临时文件 |
terminationGracePeriodSeconds: 45 | 配合 preStop 完成数据刷出 |
preStop | 容器停止前刷出采集缓冲区 |
initialDelaySeconds: 20 | 运行期安装约需 90 秒,探针需留出时间 |
ONESUITE_PILOT_AUTO_UPDATE_ENABLED: "false" | 容器环境固定版本,由镜像发布控制升级 |
emptyDir | 如需跨重启保留采集位点,可替换为 PVC |
方式二:镜像接入
在镜像构建阶段完成安装与插件注入,容器启动为秒级。不同 Agent 的基础镜像、配置目录和插件校验方式可能不同,下文以 OpenCode 为例进行介绍。
步骤1:配置 Dockerfile
构建阶段只使用占位凭证。使用其他 Agent 时,请替换基础镜像、配置文件路径、
--agents 参数和插件校验命令。镜像层为不可变历史,真实密钥一旦写入将无法清除。因此,真实凭证必须通过 Kubernetes Secret 以环境变量方式提供。
FROM <YOUR_OPENCODE_BASE_IMAGE>USER rootRUN apt-get update && apt-get install -y --no-install-recommends \\curl ca-certificates \\&& rm -rf /var/lib/apt/lists/*ENV HOME=/home/appuserRUN mkdir -p /home/appuser && chown -R 1000:1000 /home/appuserUSER 1000WORKDIR /home/appuserENV ONESUITE_PILOT_DATA_DIR=/home/appuser/.onesuite-pilot# 预置 OpenCode 配置文件RUN mkdir -p $HOME/.config/opencode \\&& echo '{}' > $HOME/.config/opencode/opencode.json# 安装 onesuite-pilot 并注入插件# 构建阶段使用占位值,真实凭证在运行期通过环境变量提供# OpenCode 对应 opencode;接入其他 Agent 时替换为相应标识ARG INSTALLER_URL=https://onesuite-pilot-1254077820.cos.ap-shanghai.myqcloud.com/onesuite-pilot/installer.shRUN curl -fsSL --max-time 180 -o /tmp/installer.sh "${INSTALLER_URL}" \\&& bash /tmp/installer.sh install \\--cls-endpoint "placeholder.cls.tencentcs.com" \\--cls-topic-id "00000000-0000-0000-0000-000000000000" \\--cls-uin "0" \\--user-id "placeholder" \\--data-dir "${ONESUITE_PILOT_DATA_DIR}" \\--agents opencode --lang en \\&& rm -f /tmp/installer.sh# 校验插件已注入RUN grep -q "plugin.mjs" $HOME/.config/opencode/opencode.json \\&& test -f ${ONESUITE_PILOT_DATA_DIR}/plugins/opencode/plugin.mjsCOPY --chown=1000:1000 entrypoint.sh /entrypoint.shENTRYPOINT ["/entrypoint.sh"]
步骤2:配置 entrypoint.sh 与 Deployment(以 OpenCode 为例)
与方式一中的 OpenCode 示例相同。entrypoint 中的判断会自动进入已安装分支:
if [ -x "${PILOT_BIN}" ]; then"${PILOT_BIN}" start # 镜像内已安装,直接启动elseinstall_pilotfi
Deployment 可缩短探针等待时间:
readinessProbe:initialDelaySeconds: 5
步骤3:验证部署结果
镜像内
config.json 使用占位凭证,运行期由环境变量覆盖。部署后执行一次自检确认覆盖生效:kubectl -n <NAMESPACE> exec <POD> -- \\bash -c '$HOME/.local/bin/onesuite-pilot doctor'
输出中应显示实际的 Endpoint 与 TopicId,且鉴权与写入检查通过。
接入验证
请在本地终端执行以下内容。
链路自检
POD=$(kubectl -n <NAMESPACE> get pod -l user=<USER_ID> -o jsonpath='{.items[0].metadata.name}')kubectl -n <NAMESPACE> exec "$POD" -- \\bash -c '$HOME/.local/bin/onesuite-pilot doctor'
预期输出:
✅ 配置文件: endpoint=... topicId=... 密钥已配置✅ DNS 解析: ...✅ 网络连通性: ...:443 可达✅ 鉴权与写入: 探测日志已写入 topic✅ 自检通过,上报链路正常
采集状态
kubectl -n <NAMESPACE> exec "$POD" -- \\bash -c '$HOME/.local/bin/onesuite-pilot status'
用户产生对话后,预期显示:
✅ onesuite-pilot is running (PID xxx)采集: N 条事件上报: N 条成功 / 0 条失败✅ 上报正常
插件注入确认(以 OpenCode 为例)
不同 Agent 的插件配置文件和校验方式不同。OpenCode 可通过以下命令确认插件是否已注入:
kubectl -n <NAMESPACE> exec "$POD" -- \\cat /home/appuser/.config/opencode/opencode.json
预期输出:
{"plugin": ["file:///home/appuser/.onesuite-pilot/plugins/opencode/plugin.mjs"]}
控制台确认
1. 进入 CLS 控制台 > Agent 可观测,选择目标应用并单击进入观测。
2. 进入应用详情后,按以下维度确认数据是否正常:
仪表盘:查看请求数、Token 消耗、耗时分位等指标。
调用链:查看 Trace 详情。调用树结构因 Agent 类型和实现方式而异,OpenCode 示例的调用树为
enter_application → invoke_agent → react round_N → chat <model>。会话:按 Session 聚合查看多轮对话。
按
gen_ai.user.id 筛选,其值等于配置的 <USER_ID>。