很多团队对 AI Agent 的第一反应不是“它能做什么”,而是“我敢不敢把它放进网络里”。这个担心很现实:Agent 会读上下文、调用工具、访问内部服务,一旦边界不清,它就可能从“助手”变成一条难审计的网络路径。来源摘要提到的核心问题正是这个:我们并不总是知道 Agent 到底会做什么,所以需要在网络层给它套上可观察、可限制、可回滚的边界。
NGINX 和 OpenTelemetry 的组合适合做这件事:NGINX 负责把 Agent 的出站或入站流量收口,OpenTelemetry 负责把请求链路、延迟、状态码、调用目标这些信号送进观测系统。它不能让 Agent “绝对安全”,但能把不可见的行为变成可检查的流量记录。
Agent 不应该直接裸连内网
传统服务的调用路径通常比较稳定:服务 A 调服务 B,接口、权限、频率都能提前建模。Agent 不一样,它的行为更像一个运行时决策系统:根据 prompt、工具描述、外部响应不断选择下一步。
这带来几个工程风险:
- 请求目标不稳定:一次任务可能访问多个内部 API 或外部 SaaS。
- 失败模式更复杂:工具调用失败后,Agent 可能重试、换路径或生成新的请求。
- 审计粒度容易缺失:如果只看最终业务结果,很难还原它中间访问过什么。
- 权限容易漂移:把一个宽权限 token 交给 Agent,等于把一大片网络能力交给了模型驱动的流程。
因此更稳妥的做法是:让 Agent 只知道一个受控入口,比如 http://agent-egress.local,由 NGINX 决定它能转发到哪里、记录什么、拒绝什么。
NGINX 做边界,OpenTelemetry 做证据
可以把这个边界拆成两层职责。
NGINX 侧重点是控制:
- 只允许访问白名单上游。
- 对敏感路径做拒绝或额外鉴权。
- 设置超时、请求体大小、并发和速率限制。
- 统一注入或传递 trace header。
OpenTelemetry 侧重点是观测:
- 每个 Agent 请求对应一个 trace。
- 记录上游目标、状态码、耗时和错误。
- 把 NGINX、Agent Runtime、工具服务放进同一条调用链。
- 支持事后回答“这个 Agent 到底访问了什么”。
这里的关键不是把 NGINX 当成普通反向代理,而是把它当成 Agent 的网络控制面。Agent 的工具调用越多,这个控制面越有价值。
可以这样实践:一个最小可改造的边界配置
下面示例是一个可改造的本地实验:用 Docker Compose 启动 NGINX、OpenTelemetry Collector 和 Jaeger。假设你的 Agent 只允许访问一个内部工具服务 tool-api:8080,所有请求都必须经过 NGINX。
创建 docker-compose.yml:
services:
nginx:
image: nginx:1.25
ports:
- "8088:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- tool-api
tool-api:
image: hashicorp/http-echo:1.0
command:
- "-listen=:8080"
- "-text={\"ok\":true,\"service\":\"tool-api\"}"
otel-collector:
image: otel/opentelemetry-collector-contrib:0.96.0
command: ["--config=/etc/otelcol/config.yaml"]
volumes:
- ./otel-collector.yaml:/etc/otelcol/config.yaml:ro
ports:
- "4317:4317"
- "4318:4318"
depends_on:
- jaeger
jaeger:
image: jaegertracing/all-in-one:1.53
ports:
- "16686:16686"
创建 nginx.conf。这个版本使用标准 NGINX 镜像可直接运行,先把边界行为和结构跑起来;如果你的 NGINX 构建包含 OpenTelemetry 模块,可以在此基础上接入原生 trace 导出。
events {}
http {
log_format agent_json escape=json
'{'
'"time":"$time_iso8601",'
'"request_id":"$request_id",'
'"remote_addr":"$remote_addr",'
'"method":"$request_method",'
'"uri":"$request_uri",'
'"status":$status,'
'"upstream":"$upstream_addr",'
'"upstream_status":"$upstream_status",'
'"request_time":$request_time'
'}';
access_log /var/log/nginx/access.log agent_json;
limit_req_zone $binary_remote_addr zone=agent_limit:10m rate=5r/s;
upstream allowed_tool_api {
server tool-api:8080;
}
server {
listen 80;
location = /tools/search {
limit_req zone=agent_limit burst=10 nodelay;
proxy_set_header X-Request-Id $request_id;
proxy_set_header X-Agent-Boundary "nginx";
proxy_set_header Host $host;
proxy_pass http://allowed_tool_api/;
}
location / {
return 403 '{"error":"agent egress denied"}\n';
add_header Content-Type application/json;
}
}
}
创建 otel-collector.yaml。这个 Collector 配置先把 OTLP 接收和 Jaeger 导出准备好,供你的 Agent Runtime 或带 OpenTelemetry 模块的 NGINX 发送 trace。
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch: {}
exporters:
otlp/jaeger:
endpoint: jaeger:4317
tls:
insecure: true
logging:
verbosity: basic
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp/jaeger, logging]
启动并测试:
docker compose up -d
curl -i http://localhost:8088/tools/search
curl -i http://localhost:8088/admin/secrets
docker compose logs nginx --tail=20
你应该看到 /tools/search 被代理到 tool-api,而 /admin/secrets 被 NGINX 拒绝。随后打开 Jaeger UI:
open http://localhost:16686
如果你的 Agent 应用已经接入 OpenTelemetry,可以把 trace 发到 Collector:
export OTEL_SERVICE_NAME=agent-runtime
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
export OTEL_TRACES_EXPORTER=otlp
需要改的地方很明确:把 tool-api:8080 换成真实工具服务,把 /tools/search 换成 Agent 允许调用的路径,把限流、超时、鉴权按你的风险等级收紧。
不要只记录成功请求
Agent 边界最有价值的日志往往不是成功请求,而是被拒绝的请求、超时请求、重试请求和访问未知路径的请求。这些信号能暴露 prompt 注入、工具描述误导、权限配置过宽等问题。
可以在告警里重点盯这些模式:
403增多:Agent 正在尝试访问未授权路径,可能是任务设计问题,也可能是输入被诱导。5xx增多:工具服务不稳定,Agent 可能进入重试循环。- 请求时间变长:上游慢会放大 Agent 的整体任务延迟。
- 新路径出现:说明工具调用面发生变化,需要重新审查。
边界策略也要分层。开发环境可以偏宽,方便观察 Agent 行为;生产环境应当默认拒绝,只开放经过评审的工具路径。不要把“我们有 trace”误解为“我们可以放开网络”。可观察性是证据,不是权限模型。
落地清单
接入这类边界时,可以按下面顺序推进:
- 让 Agent 所有工具调用先经过单一代理入口。
- 用 NGINX 白名单限制上游域名、路径和方法。
- 给每个请求生成或传递 request id / trace id。
- 将 Agent Runtime、NGINX、工具服务的遥测汇总到同一个 OpenTelemetry Collector。
- 对拒绝请求、未知路径、异常重试和高延迟设置告警。
- 定期审查工具列表,移除不再使用的网络能力。
这套方案的边界也要讲清楚:NGINX 不能理解模型意图,OpenTelemetry 不能阻止恶意调用,它们提供的是网络层收口和行为证据。真正可靠的 Agent 运行环境还需要最小权限 token、工具级鉴权、输入过滤、输出校验和人工审批。把网络边界先立起来,是因为它简单、可验证,而且一旦出事,能让你知道请求从哪里来、去了哪里、为什么被放行或拒绝。