首页
/ 使用 Terraform Provider 管理 LiteLLM Proxy 上的 A2A Agent(litellm_agent 资源完整指南)

使用 Terraform Provider 管理 LiteLLM Proxy 上的 A2A Agent(litellm_agent 资源完整指南)

2026-09-08 17:20:52作者:卓炯娓

LiteLLM 官方 Terraform Provider(仓库位于 terraform/provider/)提供了 litellm_agent 资源,用于以 Infrastructure as Code 的方式在 LiteLLM Proxy 上管理遵循 A2A(Agent-to-Agent)协议的智能体。本文围绕该资源的 HCL 用法展开,逐项讲解 agent_card_paramslitellm_paramsobject_permission、请求头转发与四组限流参数的字段语义,并结合 Provider 的 Go 实现与 LiteLLM Proxy 的 /v1/agents 管理端点源码,说明其底层 CRUD 行为、状态刷新规则、敏感值处理与 import 注意事项,帮助读者把 Agent 的注册、授权、限流全部纳入 Terraform 版本化管理。

一、A2A Agent 与 litellm_agent 资源定位

在 LiteLLM 中,A2A Agent 是指可以被发现(discover)、被调用(invoke)并通过 A2A 协议进行编排的 AI 实体。LiteLLM Proxy 将这些 Agent 以统一卡片形式注册为代理侧对象,配合模型(models)、MCP Server 等资源一起被网关统一纳管。

Terraform Provider 中的 litellm_agent 资源即对应这一对象的管理入口。它在 Provider 侧(Go 代码)封装了对 Proxy 管理端点的全部操作,对应的端点常量为 resource_agent.go

  • POST /v1/agents:创建 Agent;
  • GET /v1/agents/{agent_id}:读取单个 Agent;
  • PATCH /v1/agents/{agent_id}:更新 Agent;
  • DELETE /v1/agents/{agent_id}:删除 Agent。

这些端点与 LiteLLM Proxy 路由实现 agent_endpoints/endpoints.py 中定义的 POST /v1/agentsPATCH /v1/agents/{agent_id} 等一一对应,说明该资源直接对接网关原生管理 API,而非绕行其他模块。

二、Provider 声明与整体配置骨架

使用 litellm_agent 前,需先完成 Provider 声明与连接配置。Provider 版本与 LiteLLM 版本号保持一致(例如 ~> 1.99.0 对应运行 1.99.x 的 Proxy),见 provider/README.md 的 Versioning 说明:

terraform {
  required_providers {
    litellm = {
      source  = "BerriAI/litellm"
      version = "~> 1.99.0" # 与你的 Proxy 运行版本保持一致
    }
  }
}

provider "litellm" {
  api_base = var.litellm_api_base
  api_key  = var.litellm_api_key
}

api_baseapi_key 也支持通过环境变量 LITELLM_API_BASELITELLM_API_KEY 提供,参见 docs/index.mdapi_base 应指向你的 Proxy 实例地址,Provider 管理端点中的 /v1/agents 即基于该地址拼接。

三、资源完整示例与逐字段拆解

3.1 一份可运行的完整配置

resources/agent.md 给出的完整示例覆盖了本文讨论的全部参数,是学习该资源的最佳起点:

resource "litellm_agent" "hello_world" {
  agent_name = "hello-world-agent"

  agent_card_params = jsonencode({
    protocolVersion    = "1.0"
    name               = "Hello World Agent"
    description        = "Just a hello world agent"
    url                = "http://localhost:9999/"
    version            = "1.0.0"
    defaultInputModes  = ["text"]
    defaultOutputModes = ["text"]
    capabilities = {
      streaming = true
    }
    skills = [
      {
        id          = "hello_world"
        name        = "Returns hello world"
        description = "just returns hello world"
        tags        = ["hello world"]
        examples    = ["hi", "hello world"]
      }
    ]
  })

  litellm_params = jsonencode({
    make_public = false
  })

  object_permission = jsonencode({
    models      = ["gpt-4-proxy"]
    mcp_servers = ["my-mcp-server-id"]
  })

  static_headers = {
    "x-api-key" = var.agent_api_key
  }

  extra_headers = ["x-request-id"]

  tpm_limit         = 100000
  rpm_limit         = 1000
  session_tpm_limit = 10000
  session_rpm_limit = 100
}

配置块逻辑清晰:先用 A2A Agent Card 描述"这个 Agent 是谁、有什么能力",再用 litellm_params 描述"网关侧如何代理它",接着用 object_permission 划定访问范围,最后通过请求头与限流字段约束运行时行为。

3.2 必填字段:agent_nameagent_card_params

  • agent_name(Required):Agent 在 Proxy 上的名称,必须全局唯一。它对应底层请求体中的 agent_name 字段。
  • agent_card_params(Required):以 JSON 对象字符串形式提供的 A2A Agent Card(HCL 中用 jsonencode 构造)。支持标准 A2A Card 的全部常用字段,包括 namedescriptionurlversionprotocolVersioncapabilitiesskillsdefaultInputModesdefaultOutputModespreferredTransporticonUrlproviderdocumentationUrl 等。

这里有一个非常值得注意的行为:LiteLLM Proxy 在存储 Card 时会并入 LiteLLM 前端字段(例如 supportedInterfaces),因此 Provider 在设计上让配置值保持权威性(authoritative in state),即只要你在 HCL 中写了 agent_card_params,刷新状态时就不会用 API 返回的、被合并过的 Card 覆盖它。该逻辑在 resource_agent.go 的 Read 实现中非常明确:仅在 state 中 agent_card_params 为空(典型场景是 import)时,才从 API 回填 Card。

Go Schema 中还为 JSON 字符串字段挂载了 agentSuppressEquivalentJSON 作为 Diff 抑制函数(resource_agent.go)。它会把新旧 JSON 各自反序列化后再用 reflect.DeepEqual 比较,从而避免因 key 顺序、空白符差异而触发无意义的计划变更——这意味着你的 Card 即使调整了字段书写顺序,只要语义对象相同,Terraform 就不会产生 diff。

3.3 可选但关键:litellm_params(敏感)

litellm_params(Optional, Sensitive):LiteLLM 专有参数的 JSON 对象字符串。它可能包含 api_key 等密钥,因此 Provider 永远不会从 API 回读该字段;以你在 HCL 中配置的值为准(configured value is authoritative)。上例中的 {"make_public": false} 即通过该字段控制 Agent 是否公开展示。

测试 resource_agent_test.go 直接演示了这一设计:测试数据同时配置了 litellm_params: {"model": "gpt-5.2", "api_key": "sk-secret"},随后 Read 阶段 API 即便返回了掩码值 sk-1****,测试也断言 state 中的 litellm_params 仍保持原始配置 sk-secret(见 resource_agent_test.go),绝不会被回读值污染。

3.4 访问控制:object_permission

object_permission(Optional):以 JSON 对象字符串形式表达的访问控制权限,键支持:

  • mcp_servers
  • mcp_access_groups
  • mcp_tool_permissions
  • models
  • agents

上例将 models 限定为 ["gpt-4-proxy"]mcp_servers 限定为 ["my-mcp-server-id"],表示该 Agent 只允许访问这些模型与 MCP Server。与 agent_card_params 一致,object_permission 同样带 JSON 等价 Diff 抑制,且在非 import 场景下以配置值为权威。

3.5 请求头控制:static_headersextra_headers

  • static_headers(Optional, Sensitive):随 Agent 请求发出的静态请求头 Map。它可能携带 token(如示例中的 x-api-key),因此与 litellm_params 一样永不从 API 回读。在 Go Schema 中类型为 schema.TypeMap、元素为字符串(resource_agent.go)。
  • extra_headers(Optional):需要透传给 Agent 的入站请求头名称列表。示例中的 ["x-request-id"] 表示:当客户端带 x-request-id 头访问该 Agent 时,Proxy 会将其原样转发给 Agent 后端。它对应底层响应结构中的 extra_headers []string 字段,且该字段是可回读的(Read 时会从 API 同步回 state)。

两个字段的差异本质在于敏感度:值是"常量密钥"的进 static_headers,值是"从入站请求动态提取的头部名称"的进 extra_headers

3.6 限流参数:四组 TPM/RPM 限制

资源支持四个可选整数限制字段,对应 Proxy 侧 Agent 的 agentAPIResponse 结构体(resource_agent.go):

参数 含义 文档示例值
tpm_limit Agent 每分钟 Token 数上限 100000
rpm_limit Agent 每分钟请求数上限 1000
session_tpm_limit 单会话每分钟 Token 数上限 10000
session_rpm_limit 单会话每分钟请求数上限 100

这四个字段在 API 响应中为指针类型(*int),Read 时仅当非 nil 才写入 state,可据此推断:若 Proxy 返回的某字段为空值,Terraform 会将其按零值/缺省处理。将它们与 modelsmcp_servers 权限配合,即可为一个 Agent 同时框定"能用什么资源"与"用多快"两层边界。

四、底层 CRUD 实现与状态管理

4.1 生命周期映射

resource_agent.go 的资源定义看,litellm_agent 走完整 CRUD 生命周期:

  • Create:调用 buildAgentData 聚合出请求体后 POST /v1/agentsbuildAgentDataresource_agent.go)先把 agent_card_params 解析为 JSON 对象,再按需附加 litellm_paramsobject_permission,以及 static_headersextra_headers 与四组限流字段。若 agent_card_params 不是合法 JSON 对象,会直接报错——测试 resource_agent_test.go"not-json" 入参验证了这一校验。创建成功后将响应中的 agent_id 写入 d.SetId(),随即触发一次 Read 以刷新 state。
  • ReadGET /v1/agents/{agent_id}。当 API 返回 404 时,Provider 会将该资源 ID 清空并从 state 中移除(resource_agent.go),确保外部删除不会造成 state 与真实状态脱节。
  • UpdatePATCH /v1/agents/{agent_id},携带与 Create 相同结构的请求体,属于整体覆盖式更新,完成后同样回读刷新。
  • DeleteDELETE /v1/agents/{agent_id},随后清空 ID;对 404 做了幂等容忍(不报错、正常完成删除语义)。

这些行为全部有 httptest mock 服务器级别的单元测试覆盖(如 resource_agent_test.go 断言 Update 必须走 PATCH /v1/agents/agent-123resource_agent_test.go 断言 Delete 必须走 DELETE),可作为"资源确实按此协议工作"的实现级证据。

4.2 敏感字段为何"只写不回读"

litellm_paramsstatic_headers 的 Sensitive 语义来自安全设计而非 Terraform 限制:LiteLLM Proxy API 出于防泄漏考虑,从不返回这些字段的未掩码值(测试 mock 中返回的就是 sk-1****)。因此 Provider 在 Read 中对二者不做任何回填,state 与真实状态均以配置为准。

这一设计带来一个实用推论:对这两个字段做原地修改时,计划里看到的变更就是真实要发送的变更;但也意味着如果你在配置外手工改动 Agent 的密钥,Terraform 无法感知漂移。对密钥的轮换应始终通过修改 HCL 并 apply 进行。

4.3 Read 的"选择性回填"细节

对其他字段,Read 的逻辑是"只在 state 为空时才从 API 回填"(如 agent_card_paramsobject_permission),而 extra_headers、限流字段与审计属性(created_atupdated_atcreated_byupdated_by)则每次 Read 都从响应同步。测试 resource_agent_test.go 验证了 import 场景下 agent_card_params 会被正确填充为可解析的 JSON,同时 litellm_params 仍保持为空字符串(因为不可回读)。

五、导出属性(Attribute Reference)

除上述参数外,资源导出以下只读属性(可在引用处直接读取,如 litellm_agent.hello_world.id):

属性 说明
id LiteLLM 分配的 Agent ID
created_at Agent 创建时间戳
updated_at Agent 最近更新时间戳
created_by 创建该 Agent 的用户
updated_by 最近更新该 Agent 的用户

这些审计属性在 Go 的 agentAPIResponse 中均有对应 JSON 字段(resource_agent.go),数据来源即 Proxy /v1/agents/{agent_id} 的真实响应。

六、导入既有 Agent(Import)

已经通过控制台或 API 创建好的 Agent 可以纳入 Terraform 管理,导入命令按 Agent ID 进行:

terraform import litellm_agent.example <agent_id>

Resource 层通过 schema.ImportStatePassthroughContext 直接以传入 ID 落库,随后走正常 Read 流程。

需要特别留意文档中的提示:由于 litellm_paramsstatic_headers 含有密钥,API 永远不会返回它们的未掩码值,因此import 后这两个字段无法恢复。正确流程是:import 完成后立即在 HCL 中补齐这两个字段的配置并执行 terraform apply,让配置值重新成为权威来源,否则后续 plan 会一直显示这两个字段的追加变更。

七、配套数据源:只读查询现有 Agent

除资源外,Provider 还提供只读数据源,便于在配置中引用已存在的 Agent。单个查询数据源 docs/data-sources/agent.md 用法如下:

data "litellm_agent" "existing" {
  agent_id = "123e4567-e89b-12d3-a456-426614174000"
}

output "agent_card" {
  value = jsondecode(data.litellm_agent.existing.agent_card_params)
}

数据源暴露 agent_nameagent_card_paramsobject_permissionextra_headers、四组限流字段以及额外的 spend(该 Agent 累计消费额)。其底层实现 data_source_agent.go 直接复用资源相同的 GET /v1/agents/{agent_id} 端点与 agentAPIResponse 解析结构;查询不存在的 Agent 会直接报错(与资源在 404 时清空 ID 的行为形成对照)。

安全上,数据源刻意不暴露 litellm_paramsstatic_headers,原因正是它们可能含有 API Key 或 token(见 data-sources/agent.md 的 Security Note)。

此外还有列表形态的数据源 litellm_agents(见 data_source_agent.go),它通过 GET /v1/agents 拉取全部 Agent,并支持可选的 health_check = true——开启后 Proxy 会逐个探测各 Agent 的 URL,仅返回可达或未配置 URL 的 Agent,适合做网关侧 Agent 健康度巡检。

八、写在最后:把 A2A Agent 纳入 GitOps 的建议

综合文档与源码,把 A2A Agent 用 Terraform 管理时,以下几个实践能避免最常见的坑:

  1. Agent Card 与状态一致性:Proxy 会向 Card 合并 supportedInterfaces 等自有字段,但 Provider 已用"配置值权威 + JSON 等价 Diff 抑制"消解了这一冲突,因此放心书写结构清晰的 jsonencode Card 即可,不必手工比对 API 返回的完整 Card。
  2. 敏感字段永不漂移检测litellm_paramsstatic_headers 只写不回读,密钥轮换请始终通过 HCL 变更 + terraform apply 完成,不要绕过 Terraform 直接在 Proxy 上改。
  3. import 后必须补配置:导入的 Agent 请立即补齐上述两个敏感字段再 apply,否则会出现持续的 plan 差异。
  4. 权限与限流一同交付:用 object_permission 约束 Agent 可触达的 modelsmcp_serversagents 等资源,同时用四组 TPM/RPM 参数限定用量,使 Agent 注册本身就带齐安全边界,配合数据源实现"既可写、可查、可审计"的完整闭环。

对于希望进一步深入源码的读者,推荐阅读 Provider 侧 resource_agent.godata_source_agent.go 与全套行为测试 resource_agent_test.go,以及 Proxy 侧的路由实现 agent_endpoints/endpoints.py,两相对照即可完整还原 Agent 从 Terraform 声明到 Proxy 落库的完整链路。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
858
1.35 K
docsdocs
暂无描述
Markdown
899
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
923
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.83 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
532
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
524
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
393