AI智能体在企业里跑得越多账号问题就越扎眼。以前给服务一个固定账号就能跑现在Agent要自主调API、读数据、写工单权限和身份变成一团乱麻。我最近在实践“AI智能体企业级身份管理”时把方案落到了Active Directory上基于AD做了一层agent-directory身份适配服务算是把身份底座彻底理顺了。这篇实战记录适合已经有AD域环境、又想让Agent安全接入业务系统的团队。直接说结论agent-directory不是一个新造的目录服务它更像“AI智能体的身份代理层”。AD还是那个AD负责承载账号和组agent-directory负责把AD的身份模型翻译成Agent运行环境能消费的令牌同时把权限策略、审计、生命周期管理一并串起来。下面按我的部署思路一步步把关键环节拆开。1. 为什么AI智能体需要企业级身份管理1.1 传统身份体系遇到Agent时代的三个冲击先别急着聊技术实现回到一个更基本的问题为什么不能把Agent当成普通程序账号来管我梳理下来传统身份体系在Agent时代至少经受三个冲击。第一个冲击是“身份主体从人变成程序”。过去AD里的账号都对应员工做权限申请、审批、年度复核都是按人来的。现在Agent不是人但它要访问邮箱、数据库、工单系统甚至代表用户买东西。如果我们只是随便建一个“svc_agent”账号给个固定密码那这个Agent在系统里到底是谁出了问题谁能对它负责所以Agent也需要一个清晰的企业身份这个身份必须登记在册、可禁用、可删除和员工身份一样有完整的生命周期。第二个冲击是“权限需求从静态变成动态”。人通常申请一组固定权限干一类工作。但Agent往往在一个任务里动态决定要调用哪些工具也许这次任务只需要读订单下次任务需要写订单还可能某个临时指令要求访问财务数据。如果按传统方式给Agent长期授权权限必然越铺越宽出事的概率直线上升。更合理的做法是Agent每次执行任务都临时申请最小权限用完即回收。第三个冲击是“审计责任链必须完整”。企业内部现在越来越强调零信任和合规每一笔操作都要能追溯到主体。人在系统里的行为可以用AD账号钉住但Agent在中间调了好几个服务反复转发用户请求如果身份没有统一管理责任链很快断掉。你压根说不清是哪个Agent、代表哪个用户、用哪个权限执行了那次敏感操作。这个场景下身份管理就不再是“让Agent能登录”的问题而是“让Agent每一次动作都有据可查”。结合这三点AD这种企业身份底座依然非常合适。它已经有成熟的账号模型、组织单元、组策略和Kerberos体系覆盖率高。与其推翻重来不如在AD之上加一层给Agent专用的“身份适配层”这就是agent-directory的核心出发点。1.2 agent-directory在场景中的定位agent-directory这套做法的定位很清楚它是连接Active Directory与AI Agent运行时的“身份管道”。左边是AD右边是各类Agent应用和API网关。agent-directory本身不保存用户的完整账号密码体系它只维护Agent实例与AD账号之间的映射关系并把这种映射转换为短时有效的访问令牌。Agent拿到的令牌只够在规定权限范围内工作拿不到AD管理凭据更接触不到底层密码。它主要解决三个具体问题。一是账号生命周期管理所有Agent账号在AD的专用OU里创建agent-directory统一编排启用、禁用、删除不会出现人走了Agent还挂着账号的情况。二是动态授权Agent执行任务时可以通过agent-directory申请临时权限设置有效期限过期自动失效。三是审计可观测每次Agent身份调用都会被记录成结构化日志包含Agent ID、AD账号、资源路径、操作结果后续可以直接对接SIEM平台。这个方案并不是万能的。如果公司还没有AD域环境我还是建议先把基础身份体系建起来再考虑agent-directory。如果只是个人电脑上跑几个实验脚本那也没必要上这套重量级方案。它最舒服的场景是那种已有几百上千台机器、几十个内部系统、又刚刚开始批量引入AI Agent的中大型企业环境。2. agent-directory的架构设计与核心组件2.1 整体调用流程AD、agent-directory、Agent运行时先说一条完整的访问链路这样后面看部署就有画面感。以Agent读取订单数据为例Agent启动先向agent-directory发起身份初始化请求。agent-directory校验Agent实例是否可信包括服务器地址、启动令牌、Agent ID。agent-directory以预设的服务账号身份与AD通讯获取该Agent对应的AD账号相关状态。agent-directory为Agent生成一个短期访问令牌令牌里只放必要信息Agent ID、所属OU、权限范围、会话ID。Agent携带令牌访问内部API网关网关通过agent-directory发布的公钥校验令牌并解析权限。网关在审计系统里记录这次请求同时返回脱敏后的业务数据。这个链路里AD自始至终只和agent-directory打交道Agent并不直接理解Kerberos、LDAP这些底层协议。AD关注的是“账号是否有效、属于哪些组”agent-directory关注的是“Agent对应哪个账号、允许干什么”Agent运行时关注的是“拿着令牌去请求”。每一层只负责自己的事职责边界很清晰。为什么不建议让Agent直接连AD最直接的原因是安全。如果每个Agent都直接配置AD服务账号的密码或密钥凭据部署面会非常广泄露风险不可控。再有不同Agent的SDK和语言栈差异很大你不可能给每个框架都做一遍Kerberos集成。agent-directory把敏感凭据留在服务内部对外只暴露短时令牌和统一SDK明显更好维护。2.2 关键设计Agent账号与AD组织单元的映射在AD侧我建议专门划出一个独立OU名称类似“AI-Agents”和普通员工账号完全分开。这个OU下面再按业务线分子OU比如“Ops-Agents”、“Data-Agents”每个Agent对应一个唯一AD账号。账号命名统一使用svc_agent_前缀后面跟业务名方便一眼辨认。这是我当时在测试环境里创建OU和账号用的PowerShell命令可以直接参考New-ADOrganizationalUnit -Name AI-Agents -Path DCyourdomain,DClocal New-ADOrganizationalUnit -Name Ops-Agents -Path OUAI-Agents,DCyourdomain,DClocal New-ADUser -Name svc_agent_ops -SamAccountName svc_agent_ops -UserPrincipalName svc_agent_opsyourdomain.local -AccountEnabled $true -Path OUOps-Agents,OUAI-Agents,DCyourdomain,DClocal -PasswordNeverExpires $false创建完账号后账号策略也要跟上。Agent服务账号不能允许交互登录限制只能从Agent运行专用服务器登录。可以用AD用户属性的“登录到”功能或者用PowerShell的LogonWorkstations参数来控制。另外账号密码应该交给agent-directory托管和轮换不要让Agent端保存明文密码。这里还有一个容易踩的坑很多人图省事把Agent账号加进Domain Admins。这绝对不行Agent一旦被攻破等于给了攻击者一把万能钥匙。合理的做法是Agent账号只加入业务专用组数据权限全部通过组授权别碰高权限组。2.3 安全边界与设计取舍讲到对外令牌我建议生产环境优先使用JWT而且有效期一定要短。很多人会纠结JWT和Opaque Token怎么选。JWT的好处是无状态API网关本地校验即可压力小适合高并发但缺点是吊销麻烦只能等过期。Opaque Token需要agent-directory集中校验可以随时踢下线但每一次请求都要访问一次agent-directory容易成为瓶颈。折中的做法是JWT设成5到15分钟过期配合短TTL来规避吊销问题。真要立刻吊销某个Agent可以在agent-directory侧维护一个blacklist网关校验时缓存这个列表。API网关侧校验JWT时需要提前拿到agent-directory签发的JWKS公钥。这里给出一个网关侧的校验思路def authorize(token): claims verify_jwt(token, jwks_urihttps://agent-directory.yourdomain.local/.well-known/jwks.json) if not claims: return 401 agent_id claims[sub] ous claims[groups] if not has_permission(agent_id, ous, request.path): return 403 claims[session_id] claims.get(sid, ) return claims实际上AD组和细粒度策略应该分工AD组负责粗粒度“能访问哪个服务”agent-directory的策略表负责细粒度“能操作这个服务的哪些动作”。比如AD组可以确保Agent能访问订单服务但agent-directory进一步限制它只能调用GET接口、不能删除数据。这个两层模型是我在实战里觉得最顺手的。3. 部署实操从零搭建agent-directory3.1 前置环境准备与检查清单搭建agent-directory之前先花十分钟确认基础环境。我列一个清单你对照着自己检查检查项建议要求说明AD域环境至少一台域控生产建议两台以上域控时区、NTP必须同步DNS解析内网DNS解析正常AD依赖DNS发现服务应用服务器Linux/Windows均可推荐Linux 2核4G以上运行agent-directory服务服务账号AD中预置一个agent-directory专用服务账号用于连接AD并读取AI-Agents OU证书申请一个内部CA签发的TLS证书必须启用LDAPS或Kerberos加密LDAPS这条尤其重要。如果agent-directory和AD之间的通信走明文LDAP账号数据、令牌都可能暴露在网络上。我见过有人在内网测试图省事没开加密后来被安全团队扫描出来被迫全部重配。生产环境必须启用LDAPS或至少使用协商加密证书直接用内部企业CA签发就行。3.2 安装agent-directory服务假设你已经拿到了agent-directory的安装包安装过程并不复杂tar -zxvf agent-directory-v1.4.0.tgz cd agent-directory ./install.sh安装脚本会创建默认配置目录、日志目录、状态数据库目录。装完以后先别急着启动把核心配置文件写好。这是我最常用的一个最小配置ad: url: ldaps://dc01.yourdomain.local:636 bind_dn: CNagent-directory-svc,OUServiceAccounts,DCyourdomain,DClocal base_dn: DCyourdomain,DClocal agent_ou: OUAI-Agents,DCyourdomain,DClocal agent: token_ttl: 300 signature_key_uri: file:///etc/agent-directory/signing.pem jwks_uri: https://agent-directory.yourdomain.local/.well-known/jwks.json policy: default_deny: truead.url就是AD的LDAPS地址bind_dn是agent-directory用来查询AD的专用服务账号agent_ou是你刚才建的Agent OU。配置里最容易写错的是base_dn和bind_dn少一个逗号都会导致连接失败。token_ttl是令牌有效期单位秒300就是5分钟可以根据业务调整。default_deny建议始终为true没有配置权限时默认拒绝安全底线。agent-directory还需要一个状态存储用来保存Agent实例与AD账号的映射、当前有效的Token、操作审计日志。小规模部署用SQLite起步就够了测试阶段非常省事。生产环境建议换成PostgreSQL并发和可靠性都更稳。这一步别偷懒后面做多实例高可用时共享数据库是刚需。3.3 配置AD中的Agent账号策略AD账号创建好了接下来把策略收紧。一是限制登录位置。Agent账号只能从Agent运行服务器登录比如只有agent-app01和agent-app02可以。PowerShell里这样设置Set-ADUser -Identity svc_agent_ops -LogonWorkstations agent-app01,agent-app02二是密码轮换。Agent端的密码并不能直接交给Agent而是要由agent-directory统一管理。agent-directory会定期通过AD LDAP接口修改密码然后把新密码加密存放在自己的密钥库里。这样就算Agent服务器被入侵攻击者也拿不到AD服务账号的长期密钥。三是账号启用状态。Agent账号平时应该保持禁用只有Agent实例启动并完成双向校验后agent-directory才会临时启用对应账号。很多团队会忘记这一步导致所有Agent账号常年处于可登录状态扩大攻击面。记住Agent不工作时它的AD账号就应该“睡着”。3.4 创建第一个Agent身份并完成对接环境准备完可以创建第一个Agent身份了。我习惯用命令行工具操作agent-directory agent create \ --name ops-assistant \ --ad-account svc_agent_ops \ --ou OUOps-Agents,OUAI-Agents执行成功会返回一个agent_id和secret_id这个secret_id相当于Agent的初始身份密钥。把这两个值配到Agent运行时环境变量里不要写进代码仓库。Agent侧对接按SDK来。我们当时用Python写的Agent示例是from agent_directory_sdk import AgentClient client AgentClient( agent_idag-ops-assistant-001, secret_idsid_xxx, service_urlhttps://agent-directory.yourdomain.local ) token client.obtain_token(scopeinternal-api:read)obtain_token会先完成Agent实例与agent-directory之间的验证然后向AD确认账号状态最后下发一个短时有效的JWT。拿到token后Agent就可以正常访问被保护API了。又是个很容易被忽略的细节Agent机器的时间必须和AD域控保持严格同步。JWT的签发时间和验证时间一旦偏差超过容忍范围会直接导致验签失败。很多莫名其妙的401最后查出来就是系统时间偏了。4. 实战让Agent安全调用企业内部API4.1 需求拆解与权限规划用一个具体场景来演示。假设企业内有一个“订单查询服务”现在业务Agent需要根据用户输入去查订单状态但和用户对话时不能展示完整手机号只能脱敏显示。这个需求拆开看实际上有三层限制Agent只能访问订单API只能使用GET方法响应里的敏感字段必须被脱敏。普通AD组只能解决第一层后面两层要在agent-directory策略表里补齐。规划结果可以整理成一张表权限维度配置位置具体规则服务可达性AD组将Agent账号加入“AG-Order-Reader”组资源路径与动作agent-directory策略允许GET /api/v2/orders/*响应字段脱敏API网关脱敏规则隐藏手机号中间四位这种两层授权模型的好处是AD组能快速控制服务入口agent-directory策略则精准控制Agent内部行为。即便AD组误授权agent-directory也能把动作限定在只读范围。这是最小权限的真正落地方式。4.2 核心流程获取令牌并访问资源Agent获取到令牌后实际请求API是这样的curl -X GET https://api.gateway.yourdomain.local/v2/orders?userU1001 \ -H Authorization: Bearer $AGENT_TOKEN网关拿到JWT后解析确认Agent有权限访问该路径再继续往下处理。脱敏这一步在API网关做最合适。用Python片段举例def mask_phone(order): phone order.get(phone, ) if len(phone) 8: order[phone] phone[:3] **** phone[-4:] return order脱敏逻辑前置到网关业务服务拿到的是已经脱敏的数据。这样Agent即使想绕过限制也没法从响应里拿到客户完整手机号。实战中最好在网关层统一做脱敏别把它散落在各个业务服务里。4.3 临时授权、权限回收与审计刚才的场景是长期只读权限但Agent也会遇到临时高权限需求。比如某个故障处理Agent需要临时写入一条配置这类权限就不应该长期存在。agent-directory支持临时授权。命令示例agent-directory auth grant \ --agent ag-ops-assistant-001 \ --permission orders:write \ --ttl 30m这条命令会创建一个30分钟有效的写入权限到期自动失效。我建议把ttl设置成任务执行时间的两倍左右太短会导致任务中途失败太长又失去临时授权的意义。更严格的场景还可以绑定“任务ID”任务结束后立即撤销权限即使Token没过期也无效。审计日志也很重要。agent-directory默认记录的字段至少应该包括字段含义timestamp操作时间agent_id发起请求的Agent IDad_account对应的AD账号target_resource访问的资源路径action操作动作result成功或失败session_id会话IDon_behalf_of如果Agent代表某个用户记录用户ID这些日志我建议全部转发到企业SIEM平台保留不少于180天。别等到出安全事故再去查日志到时候没有上下文记录责任链根本补不回来。4.4 身份责任追溯的实战心得Agent经常是代表某个真实用户执行操作这时候要特别强调“代理身份”和“最终用户身份”分离。例如用户B向企业助手Agent发起请求Agent调用订单API时令牌里的agent_id是助手Agenton_behalf_of字段则填用户B。API网关在审计日志里记录的是“AgentA代表用户B请求了订单服务”。这样以后出问题可以直接定位到具体用户和具体Agent不会出现“都是Agent干的”这种模糊责任。我在实战中还总结出一个原则Agent的权限永远不要高于它代表的用户。如果用户只是普通员工Agent调用API时也只能拥有普通员工级别的数据权限绝不能因为Agent是机器就额外放开管理权限。这条原则写进评审流程之后权限事故少了很多。5. 常见问题与排查技巧实录5.1 连不上AD或绑定失败agent-directory启动时报“cant bind to LDAP”是我见过最多的问题。通常跑完排查四步就能定位检查bind_dn是否写错尤其注意区分CN和OU的层级。检查base_dn是否与AD域匹配。检查LDAPS证书是否受信任测试环境可以临时把verify_cert设为false但生产环境不行。检查服务账号是否被锁定或者密码过期。如果AD有多个域控还要确认你连的那台域控能被agent-directory解析到。别小看DNS问题AD环境中DNS和DNS解析经常是隐身的坑。5.2 Agent拿不到令牌或令牌校验失败Agent调用obtain_token返回401或403的排查顺序agent_id与secret_id是否匹配。AD账号是否启用有没有被锁定。agent-directory到AD的账号映射是否正常。Agent服务器与域控的时间偏差是否超过阈值。JWT校验失败的另一个常见原因是网关侧的JWKS缓存过期。每次agent-directory更换签名密钥后网关必须及时拉取新的公钥。如果网关有缓存记得清一下或调短缓存时间。5.3 权限变更没生效在AD组里把Agent移除了但Agent依然能访问API别慌这大概率是缓存和票据时间的问题。Kerberos票据本身有有效期AD组变更也不会实时传递到票据中。agent-directory会缓存Agent的组成员关系和策略默认缓存时间可能比较长。排查时先重启agent-directory服务清一遍缓存再看Agent是否重新获取了Token。如果你把Token有效期设成几小时那就只能等它自然过期。所以我才一直强调Agent令牌的有效期必须短权限变更才能尽快生效。5.4 性能与可用性优化建议Agent并发量上来之后agent-directory会成为关键节点。我们当时的优化路径是使用JWT让API网关本地验签减少回调agent-directory。agent-directory增加Redis缓存缓存Agent与AD账号映射关系避免每次请求都查询AD。将agent-directory从单实例扩展为多实例前面加负载均衡共享同一个PostgreSQL状态库。对长期存活的Agent提前预取令牌避免高峰期集中申请。但也不要为了优化而优化。如果Agent只有几十个单实例加本地SQLite足够。先量化流量再决定是否需要集群。我们团队就是从单实例起步跑了几个月才加第二台每一步都有明确依据。按我实际试下来的经验最重要的一件事就是把Agent的身份独立出来并且让密钥永远待在agent-directory侧。只要身份底座是干净的后面做权限管控、审计追溯、临时授权都会顺理成章没有这个底座Agent规模一大迟早会在安全事件里付出代价。希望这套基于Active Directory的agent-directory部署思路能帮到正被Agent身份问题困扰的团队。