AI Identity:人类登录与 Agent 访问
你不再借用 identity,而是开始签发它 · 通过指挥 agent,一次一个 spec 构建
想象你的 Digital FTE 在凌晨 2 点工作,而你正在睡觉。它报销一笔费用,预订一个供应商,发送一条回复。一个问题决定这究竟安全,还是一场正在等待发生的灾难:它用了谁的 identity?
在 Connector-Native Apps 和 Plugins for AI Agents 课程中,你的 app 只是借用了运行 host 的那个人的 identity。当人类坐在椅子上时,这还可以。但一个在人类不在椅子上时也会运行的 worker,不能借用人类的 login。因为如果它以_你_的身份登录,它就_是_你:它能做你能做的一切,永远如此,而且每条 log 都会说是你做的。你无法给它设定 scope、设定时间盒,也无法收回。
这门课就是 identity 停止被借用的地方。你分两半构建它。首先,你拥有自己的 sign-in: 不再租用第三方 login,而是站起自己的 production-grade authentication,以及能签发真实 tokens 的 OAuth/OIDC server。然后,你给 agent 自己的 identity: 一份 scoped、time-boxed、revocable、human-approved 的 credential,让 worker 能代表某个人做真实工作,却永远不冒充那个人。
学完后,你会交付一个正在运行的 app(你自己机器上的真实 Next.js 项目),它会依次具备:
- 你自己的 email-and-password sign-in,包含真实 sessions 和受保护的 dashboard;
- 一个 OAuth/OIDC issuer,可以签发 signed tokens,并发布它的 keys (JWKS),让任何人都能验证;
- 一个独立的第二个 app,通过你的 issuer 让用户 sign in,同时不持有你的任何 secrets;
- 一个 resource server,可以离线验证这些 tokens,只接受为它签发的 bands;
- 以及一个 beta agent credential:AI worker 以自己的名字携带的 band,带有 scope、time box、revocation 和 human approval.
这是一门 build course,并假设你已经掌握 spec-driven loop:先就 what 达成一致,再指挥 agent 产出 how。不同于 SDD 课程,这里的主要工具不是 claude.ai。这门课是 repo-based:你会在真实 Next.js app 中使用 Claude Code 或 OpenCode。你不会手写 TypeScript;你会指挥一个 general agent,由它写代码,这和 Manufacturing track 中每门 build course 的动作相同。但这也是一门 security course,所以 code 只是一半工作:仍然属于你的部分,是明确指定要构建什么,然后检查、测试并证明每个 security property 都成立。贯穿本课的无 spec understand prompts 正是在训练这一点:decode token、篡改它的 audience、replay 它,并观察 server 拒绝请求。
📚 教学辅助材料
查看完整演示 — AI Identity:人类登录与 Agent 访问
这门课回答的一个问题
此后你构建的每个系统,都可以拿来问一个测试问题:
这是谁的 identity,authority 又如何从 human 传给 agent?
这个问题就是主脊。随着 agent-identity standards 稳定下来,具体工具会不断变化。这个问题不会变。
一张图:场馆和手环
Identity 听起来很抽象,直到你把它映射到一次夜晚外出。把这张单一图像放在脑中,本课每一部分都会扣上。
你来到一个场馆。门口有人只检查一次你的 ID:这就是 signing in,证明你是谁。他们不会让你在里面每个吧台再次出示 ID。相反,一个柜台会给你打印一条手环。手环证明你被允许进入;场馆关闭时会过期,如果你行为不当,保安可以把它剪掉。里面的调酒师只瞥一眼你的手环就服务你。手环上有一个只有柜台才能做出的封印,所以调酒师一眼就信任它,不用打电话问柜台。
这就是整个 identity stack,场景中的每一部分都对应一个术语:
同一个模型,到处使用:门口是 sign-in,柜台是 issuer,手环是 token,调酒师是 validator。在 frontier 上,agent 不再借用你的手环,而是拿到自己的手环,有时还会被盖章,表示它可以在严格限制下代表某个人行动。
注意 token 能工作的关键:调酒师从不打电话给柜台。手环上的封印已经足够。在真实系统中,这个封印是 cryptographic signature;柜台会发布任何人都能用来检查签名的 key,同时保留用来制作签名的 key。因此,一个陌生 app 可以信任你的 tokens,却永远不接触你的 database 或 secrets。
Tokens 和 sessions,从零开始
接下来全课都会反复出现三个词。用你已经持有的那张图,直接理解每一个。
Session 是服务器记住你已经 signed in 的方式。门口检查 ID 后,会在你的 browser 中放一个小标记,也就是 cookie,并在之后每个 request 中读取它,这样你不用在每个页面重新 sign in。Session 就是场馆知道你今晚已经进来了。
Token 就是手环本身:一条签名声明,说明你是谁以及你能做什么。常见类型是 JWT (JSON Web Token),由点连接的三部分组成:header.payload.signature。payload 携带 claims;signature 是柜台的封印。
接下来要一直持有这张图。柜台通过把自己的蜡封压到手环上来给手环签名。制作封印的印章,也就是柜台的 private key,锁在柜台里,永不离开,所以没人能复制这个标记。为了让世界检查封印,柜台会在门边墙上贴一张清晰照片,也就是 published (public) key。任何人都可以把手环举到照片旁边,确认封印是真的,但你不能从照片中雕出一枚可用印章。整个技巧就在这里:照片让陌生人能 verify 手环,却不能 forge 手环,而调酒师正是凭这个一眼信任。
OAuth(以及叠在其上的 OIDC,用于携带_这个人是谁_)是约定好的握手协议:柜台为另一个 app 打印手环。一个 app 把人送来 sign in,你的 server 返回 token,另一个 app 读取它。
拿任意 JWT(你的 app 几分钟后会 mint 一个,也可以粘贴示例),然后问你的 agent:"Decode this JWT. Show me the header and payload as plain JSON, explain what each claim means, and tell me which part anyone can verify with a public key and which part proves it was not tampered with." 阅读它的回答,比重读这一节更快形成直觉检查。
设置你的环境(一次)
你构建的一切都发生在一个小文件夹中:course base。它刻意保持精简:带有 constitution、specs、prompts 和一个 skill,还没有 app。你的第一步是指挥 agent 构建一个 app,这本身就是你整门课会使用的 loop 的第一次重复。
下载一次;同一个文件夹服务整门课。
或者 clone agentfactory-manufacturing repo 并打开其中的 ai-identity 文件夹。无论哪种方式,都在你的 agent 中打开这个文件夹:
cd ai-identity
claude
cd ai-identity
opencode
你还需要一个免费的 Neon Postgres database 来存放 sign-in data(无需信用卡;base 会为你接好)。在下面第二个 prompt 前先设置它。
Lesson 0 分成两个 prompts,这样你会先看到地基被证明,再在上面构建。
Step 1,证明环境。 粘贴:
Read
specs/00-set-up-the-base/spec.md(Phase 1) and the "Set up the base" section ofAGENTS.md. Check my prerequisites (Node, pnpm), install the skills it lists (Better Auth, shadcn, Neon), and confirm the MCP servers in.mcp.jsonandopencode.jsonare present and reachable. Don't scaffold anything yet. Just prove the ground and run the Phase 1 acceptance checks.
注意: npx skills add 可能会悄悄漏掉 skill 名称,所以 agent 会确认每一个确实落地。完成条件: Node 和 pnpm 报告版本,better-auth、shadcn 和 neon-postgres skills 存在,并且三个 MCP servers 都有响应。
刚刚发生了什么: 你雇来了受训人员并接通了电话,但还没有构建任何东西。skills 是柜台操作员手册(如何签发手环、如何构建 UI);MCP servers 是 agent 直连 Neon 控制室和 live docs 的线路。地基已被证明;上面还没有东西。
Step 2,scaffold app。 先 provision 你的 Neon database,然后粘贴:
Now do Phase 2 of
specs/00-set-up-the-base/spec.md: scaffold the Next.js + Tailwind + shadcn app here, pin the Better Auth 1.7 stack with the kysely override, add the Neon driver, and create.envfrom the template. Don't build any auth. Start the dev server and show me the landing page is up, then run the Phase 2 acceptance checks.
注意: create-next-app 会拒绝在非空目录中 scaffold,所以 base 的 recipe 会先 scaffold 到临时目录,再把结果 merge 回来(冲突时 base files 优先)。完成条件: pnpm dev 在 http://localhost:3000 提供一个普通 landing page,且 pnpm build 和 tsc 都 clean run。
刚刚发生了什么: 现在建筑存在了。dev server 展示了一个亮着灯的空场馆,一台真实 app 在你的机器上启动,但还没有门、柜台和手环。你有了放 identity system 的地方,而 Lesson 1 正是从这里开始构建。
Quick Win:登录你自己的 app
base ready 后,你离一个由_你_拥有、并由真实 database 支撑的 sign-in screen 只差一个 prompt。先成功,再理解。
粘贴前,先在同一张图上命名它要构建的四个部分。Email and password sign-in 是门口检查你第一次到达时设置的 ID。Session 是场馆通过前面说的 cookie 记住你今晚进来过,所以你不用每页重新出示 ID。Protected route 是只有 signed-in members 能进入的后房。Password hash 是门口保存的单向指纹,而不是你的真实密码,所以连场馆也读不回来。
Lesson 1,拥有你的 sign-in。 粘贴:
Read
specs/01-own-your-sign-in/spec.mdand thebetter-auth-best-practicesandemail-and-password-best-practicesskills. Plan the approach against our constitution, show me the plan, then build it in small steps. Run the spec's acceptance checks, including the security ones, before you call it done.
你 review plan,agent 构建,然后你创建账号并进入一个能证明你是谁的 dashboard。这就是你的 win: sign-up、sign-in、sessions 和 protected page,全都运行在你自己的 server 上。
注意: Better Auth 的 POST endpoints 会拒绝任何 Origin header 不可信的 request,所以 base 的 config 预先列出了你的 dev origin。完成条件: 你创建账号并进入显示 name 和 email 的 dashboard,而且你的 password 只以 one-way hash 形式存储,下面的 understand prompt 会证明这一点。
现在用一个 understand prompt 让它对你变得真实;它没有 spec,只是让你_看见_自己构建了什么:
I just signed up. Show me exactly what got stored in the database for my account, and point out what is NOT there. Where is my password, and why can't you show it to me?
答案是:你的 password 只以 one-way hash 存储,所以连你自己的 server 也无法读回。这是本课构建的第一块 identity literacy。你不是在段落里读到它,而是在自己的 data 上看到了它。
构建路径:从租用 login 到签发 login
这门课是一条 7 步 spine,与 base 中的 specs 一一对应。你通过粘贴一个短 prompt 来构建每一步;spec 承载细节,skill 承载确切 API,所以正文专注于 idea。下面是完整 arc,以及它从哪里开始不再是完全确定的地面。
7 步 spine,然后 milestone,然后 frontier。越往右,standards 越年轻;mental model 全程保持不变。
0–1. 设置 base,然后拥有你的 sign-in
你已经在 Quick Win 中见过这些。Step 0 scaffold toolchain(Next.js、shadcn、Better Auth 1.7 stack、Neon)。Step 1 站起 email and password sign-in,带有真实 server-side sessions 和 protected dashboard。这就是门口:你的 users 只证明一次自己是谁。
2. 成为 issuer(marquee)
这是整条 track 一直指向的步骤。在 Connector-Native Apps 中,你是调酒师:你的 gateway validated 别人签过的 tokens。这里你走到柜台后面,成为柜台。当另一个 app 把一个人送到你这里 sign in 时,你的 server 返回一个 signed token,那个 app 可以完全靠自己验证它,只需拿它对照你公开贴出的 seal photo,不需要看见 password,也不需要调用你的 database。
这就是 loop 闭合:曾经只教你检查手环的课程,现在教你打印手环。
在粘贴前,先理解你的柜台即将运行的 handshake。当 OAuth client(另一个同意承认你手环的场馆)把一个人送来 sign in 时,你不会把手环通过 browser 传回去。你运行 authorization-code flow:人在你的柜台 sign in,你给 app 一个短期 code(claim-check stub),app 在不可见处悄悄把 stub 换成真正 token,所以手环本身不会经过 browser。PKCE 是一行证明:开始 handshake 的 app,正是完成它的 app,因此被偷走的 stub 对别人没用。在任何手环打印前,人会在 consent screen 上批准 app 可以看到什么。(你前面贴在墙上的 seal photo,就是 app 拿到手环后能验证它的东西。)
这仍是 Quick Win 中同样的 plan-build-check loop,只是目标大得多。工作方式没有新东西;只是要构建的东西更重。准备好后粘贴:
Read
specs/02-become-the-issuer/spec.mdand theagent-identity-issuerskill. Plan it, show me the plan, then build it in small steps. Build the token verifier as a separate script so the checks are real, and run all the acceptance criteria, especially the adversarial ones.
你不会手写 OAuth configuration。随附的 agent-identity-issuer skill 携带 verified config,spec 携带 acceptance checks。你的工作是指挥构建,并确认它通过,包括那些 working-but-insecure version 会失败的 security gates。
你已经构建好了;现在看它是否真的安全。下面 prompts 没有 spec。每一个只是让你在自己的 issuer 上看见一个 security property。
首先,看墙上的照片。你的 JWKS endpoint 正是那面墙:你柜台 seal 的 public photo,任何人都可以拿手环来对照检查。压出 seal 的印章,你的 private signing key,锁在柜台里,绝不在照片中。
Fetch my JWKS endpoint and show me what's there. Is my private signing key in it? Prove it, and explain why a stranger can verify my tokens but can't forge one.
这个差距就是全部重点:只贴照片,绝不贴印章,世界就能 verify 你的手环,但没人能 forge 一个。
接着,读取刚打印的手环,再改一个字符把它弄坏:
Take an ID token you just issued, decode it, and walk me through every claim,
iss,aud,sub,exp, in plain English. Then change theaudby one character and show me the verifier rejecting it.
最后,把手环推过 closing time:
Issue a token, then move the clock past its expiry and try to use it. Show me the exact rejection.
刚刚发生了什么: 你走到了柜台后面。曾经教你扫一眼手环的课程,现在教你打印手环,并且带有 seal,让陌生 app 可以一眼信任每条手环,而不需要打电话给你的柜台;你也看到了 seal、audience stamp 和 expiry 都能守住。
3. Scopes 和 consent
token 应该精确说明它可以做什么,不能更多。Step 3 添加 scope(手环被允许做什么,比如盖着 drinks only 的彩色手环,而不是 drinks and kitchen)和 consent screen,让人在批准前看到确切列表。Least privilege 变成现实:手环携带完成工作所需的最窄 authority,bartender 每次点单都检查它,而不是只在门口检查一次。
你已经运行过这个 loop 两次。现在再来一次,只新增一个 idea:scope,叠在你已经构建的 issuer 上。粘贴:
Read
specs/03-scopes-and-consent/spec.mdand theagent-identity-issuerskill. Plan the approach against our constitution, show me the plan, then build it in small steps. Run the spec's acceptance checks, especially the adversarial ones, before you call it done.
现在证明限制是真实的,不是装饰。下面每个 prompt 都让你看到 scope 守住:
首先,给自己一条窄手环,然后尝试越权:
Issue me a token that has only
notes.read. Now use it to try the write action and show me the exact refusal. Then explain in plain English why a token that signs fine can still be turned away here.
然后看 person 实际看到的 approval screen:
Walk me through the
/consentscreen for a client asking fornotes.readandnotes.write. Where do those two lines come from? Prove the screen can only show what the signed request actually asks for, not whatever it likes.
最后,尝试拿到比注册更多的 authority:
Register a client for
notes.readonly, then have it ask fornotes.writeanyway. Show me the granted scope in the token it gets back and point out what is missing, and why.
刚刚发生了什么: 你的手环现在有颜色了。每条都携带完成工作所需的最窄 authority,而且在任何手环被打印前,人都看到了确切列表。
4. 连接一个真实 app
现在证明柜台不仅为你工作。client app 是一个单独场馆,通过你来让人 sign in,却不共享你的任何 secrets。把你的 issuer 叫做 AuthCo,把新 app 叫做 Notes。当有人登录 Notes 时,它会把人送到 AuthCo 的柜台,拿回手环,然后完全靠自己用 AuthCo 贴在墙上的照片检查手环 seal。Notes 永远看不到 password,也永远不碰你的 database。
同样节奏,新角色。深呼吸:你不是在构建陌生东西,只是在把第二个独立 app 指向你已经拥有的柜台。粘贴:
Read
specs/04-connect-a-real-app/spec.mdand theagent-identity-issuerskill (the register-a-client and verify-a-token sections). Plan the approach against our constitution, show me the plan, then build it in small steps. Keep Notes a fully separate process. Run the spec's acceptance checks, especially the adversarial ones, before you call it done.
现在让自己相信隔离是真的。每个 prompt 都让其中一部分可见:
首先,证明 Notes 没有持有你的 secrets:
Show me everything Notes knows about AuthCo. Prove it has no copy of
BETTER_AUTH_SECRETand no path into AuthCo's database, then explain how it can still verify my tokens.
答案还是照片:Notes 只需要 AuthCo seal 的 public photo 来检查手环,从不需要印章,所以它能验证每个 token,却不持有 AuthCo 的任何 secrets。
然后,把 audience stamp 改坏一个字符:
Take a token Notes just verified and change its
audby one character. Show me Notes's verifier rejecting it, and explain why that one character is the whole point.
最后,从柜台剪掉手环,看下一次调用失败:
Sign me in through Notes, then revoke the client at AuthCo. Make Notes's next call and show me it fails. Explain what "revocable" actually buys me here.
刚刚发生了什么: 一个你不控制的场馆,通过你的柜台让某人登录,并独立信任手环,同时不持有你的任何 secrets。柜台不仅为你工作,也为陌生人工作。
5. 连接 resource server
resource server 是一个只检查手环、从不让任何人 sign in 的吧台。这正是你在 Connector-Native Apps 中扮演过的调酒师,现在站在你自己的地盘上。它接收 bearer token,意思是持有手环的人只要出示它,不再展示其他 ID;它读取手环的 audience stamp,good at THIS bar,所以为另一个吧台 mint 的手环会被一眼拒绝。这里的 seal 使用特定 signing algorithm (RS256) 制作,任何其他方式封印的手环也会被拒绝。它把每个 seal 对照 AuthCo 发布的照片检查,并且永远不打电话给柜台;这正是下面 build prompt 中 verifying offline via JWKS 的含义。
到这里,loop 应该已经熟悉。再加一个角色:只检查手环并服务其中 named person 的吧台。粘贴:
Read
specs/05-connect-a-resource-server/spec.mdand theagent-identity-issuerskill (sections 1 and 3). Plan it, show me the plan, then build it in small steps. Configure AuthCo to sign RS256 tokens audience-bound to my API, stand up a tiny protected resource that verifies offline via JWKS, and run all the acceptance checks including the adversarial ones.
证明手环只在目标地点工作。下面每个 prompt 都把一条规则变成你能看见的东西:
首先,把两种手环并排放:
Show me two tokens side by side: the ID token from the login flow (lesson 4) and the access token a resource server gets. Point at the
audon each and explain in plain English why they're different.
然后,出示一条用错误方式封印的手环:
Sign a token with EdDSA and present it to my RS256-only verifier. Show me the exact rejection, then explain why the issuer's signing algorithm has to match what the consumer expects.
最后,把有效手环指向错误吧台:
Change the audience on a valid token to a different API's URL and show my resource server refusing it, even though AuthCo's signature is genuine.
刚刚发生了什么: 你在自己的地盘上站起了 Connector-Native Apps 中的调酒师。它检查每条手环,只服务手环中 named person,并拒绝任何为不同吧台 mint 或用错误方式封印的手环。
6. 使用 CIMD 的 client identity(edge)
Steps 0 到 5 是 settled、production-grade ground。Step 6 离开它。到目前为止,app 通过 client registration 证明_自己_是谁:它在你预先批准的 partner list 上获得位置,提前被背书。使用 CIMD (Client ID Metadata Document) 时,app 跳过列表。它在一个 URL 上挂出描述自己的 public sign,你的柜台在 app 第一次出现时按需读取该 sign,无需预注册。这是 MCP 世界正在走向的方向,但它运行在 Better Auth pre-release plugin 和 IETF draft standard 上,所以课程会让你在构建前确认 live API。
这是唯一需要在构建前查阅的地方,因为地面更新。慢一点;prompt 本身要求 agent 先检查 live docs,这正是面对移动标准时的正确本能。粘贴:
Read
specs/06-client-identity-with-cimd/spec.mdand section 2 of theagent-identity-issuerskill. Before writing anything, query the live Better Auth docs MCP athttps://mcp.better-auth.com/mcpand show me the current@better-auth/cimdAPI, whether I addcimd()or passcimdClientDiscovery()tooauthProvider, and the exact discovery key. Then plan it, show me the plan, move us to the Better Auth 1.7 pre-release channel, and build it in small steps. Run the acceptance checks including the adversarial ones.
然后看这一个 change 实际打开了什么。每个 prompt 都让新行为可见:
首先,看到你的 public sign 上出现新行:
Show me my discovery document before and after this change, and point at the one new line that tells a client "you can identify yourself by URL." Explain in plain English what that flips on.
然后看柜台读取 sign,而不是列表:
Walk me through what happens when a client hands you an HTTPS URL as its
client_id: what do you fetch, what do you read in that document, and how is that different from looking up a row in my database?
最后,给它一个坏 sign,看它拒绝:
Hand my issuer a
client_idthat is a plainhttp://URL, and one with a#fragmenton the end. Show me each one being refused, and explain why the draft insists on a clean HTTPS URL.
刚刚发生了什么: 一个 app 不再等待你的 guest list,而是通过挂出 public sign 介绍自己。agent 世界正在走向那里,而你在一个能看见它移动的地面上构建了它。
~50% milestone:你驱动的第一个项目
spine 之后,课程不再把完全指定、live-verified 的步骤交给你,而是开始交给你自己驱动的项目。第一个是 halfway mark,并且仍在稳固地面上。
Project 12-3 hours加固你的 sign-inlogin 已经能工作。现在让它难以被偷,也容易进入。
你已经拥有一个 working sign-in。working sign-in 也是 target:一个 leaked password,就有人进来了。所以你从两侧提高 stakes,使用 base 中稳定的 2fa 和 social-login specs。
两个新 ideas 承载它。second factor 是 password 之外的第二个证明:你的门卫还会检查一个只有你的手机能显示的 code,所以只复制 ID 已经不能让人进门。social login 只是第二扇门,一个 Continue with Google 入口,最终落到里面同一份 membership。
Read
specs/projects/2fa/spec.mdandspecs/projects/social-login/spec.md. Plan both, show me the plan, then build them in small steps. Harden the sign-in you already own with a second factor, and add a "Continue with Google" door. Run every acceptance check, including the adversarial security ones.
完成条件:正确 password 加错误 second factor 会被拒绝,backup code 只工作一次,"Continue with Google" 会落到 email-and-password user 的同一个 dashboard,并且任何 secret 都绝不出现在 response body 或 log 中。
刚刚发生了什么: 你的门现在要求两个 proofs,并从两侧打开;单独一个被偷的 password 已经不能让任何人进来。
Frontier:agents 的 identity
现在进入第二半,也是这门课存在的原因。到目前为止,每个 token 都代表一个 human:你 sign in,拿到手环,apps 和 gateways 信任它。但 Manufacturing path 关注的是能自主行动的 agents。因此问题变成:当 agent 做某件事时,它戴的是_谁_的手环?如果它只是复用你的 login,logs 会说是_你_做的,它能做你能做的一切,而且你无法 revoke agent 而不把自己锁在外面。这是错误答案,而修复它就是整个 frontier。
同一张图,用问题和修复来讲:
同一张图,问题与修复:今天每个 agent 都戴着你唯一 master band 的 copy,所以保安无法区分它们,也无法只剪掉其中一个。使用 agent auth 后,每个 agent 在 trusted host 下运行并戴自己的手环,server 能准确读出谁在行动及其确切 limits,并且能剪掉一个而不碰其他。
这是 why。how 是一个短 flow,每个 agent 都运行它来拿到并使用自己的手环:
这三步运行在 Better Auth 的 @better-auth/agent-auth plugin 上,它是 beta,也是 Agent Auth Protocol 的一种 implementation。请保持诚实框定:把具体 API 当作 durable primitives 的一个可替换实例,并 pin 你落地的版本。不会移动的是这张图,所以继续持有它:agent 即将拿到自己的手环。
你不是从零开始。base 为下面三步都提供了verified worked example(worked-examples/ai-identity/ 中的 answer key),每一步都是你驱动的 spec,与你已经运行六次的 loop 相同。
Agent 拿到自己的手环
到目前为止,你一直是 guest。这里有一个新 guest 走进来:AI agent。第一直觉是把它夹到_你_的手环上,但这正是 impersonation problem。相反,agent 拿到自己的手环,用自己的名字,也就是图中的 agent #7 手环。
有三件事让它不同于人类 sign-in,而这三件事就是全部 idea。第一,agent 不是单独到来;它运行在一个 host 内,也就是场馆已经信任的 runtime 或 device,由 host 为 agent 背书。第二,手环是 self-sealed and short-lived:agent 用自己的 key 签自己的手环,手环大约一分钟有效,所以被复制的手环几乎一泄露就过时(这和躺在 config file 里的 long-lived bearer token 很不同)。第三,手环让 agent 做的事情是一组 named capabilities,也就是 agent 版的 scope。你已经运行过这个 loop;现在它指向一种新 guest:
Read
specs/projects/agent-credential/spec.mdand.agents/skills/agent-identity-issuer/. Confirm the live agent-auth surface against the Better Auth docs MCP first, it is beta. Plan it, show me the plan, then build in small steps: enable autonomous agent identity, register an agent under a host, have it self-sign its own short-lived credential, and execute a granted capability. Run every acceptance check, including replay and revocation.
现在让新 idea 可见。首先,看手环上是谁的名字:
Register an autonomous agent and show me the credential it gets. Whose identity is the
sub, a person's or the agent's own? Explain in plain English why the agent having its own band is different from it reusing my login.
然后证明 short-lived、self-sealed 手环能抵抗盗用:
Take my agent's credential and replay the exact same signed band twice. Show me the second call being refused. Explain what the one-time marker is doing and why a band good for only a minute is safer than a long-lived token.
刚刚发生了什么: agent 停止借用你的手环,拿到了自己的手环。logs 现在说是 agent 做的,手环在 agent 的名字下,并且只携带授予给它的 capabilities。
On-behalf-of:盖章的手环
这是最值得做对的 credential。agent 很少纯粹为自己行动;通常它为某个人行动,危险捷径是让它变成那个人。On-behalf-of 是诚实版本:手环同时写出_双方_,agent #7, acting for Alice,所以 action 总是归属于 agent-for-Alice 这一对,而绝不是 Alice alone。这就是图中盖章的手环:for Alice, drinks only, void at midnight.
让它安全的部分是 human approval in the loop。agent 不能自己 mint 这条手环。它提出请求,Alice 收到 prompt(device-code flow,和把电视登录到 streaming account 的模式一样),并在任何 authority 存在之前说 yes。没有 approval,就没有手环。并且因为 Alice 是 authority 的来源,她可以把它收回:revoke 后,agent 的下一次调用会失败。粘贴:
Read
specs/projects/on-behalf-of/spec.mdand.agents/skills/agent-identity-issuer/. Confirm the live agent-auth surface against the Better Auth docs MCP first, it is beta. Plan it, show me the plan, then build in small steps: enable delegated mode, have an agent request a scoped capability, gate it behind human device-code approval, and only then let it act. Run every acceptance check, including no-approval-no-grant and revocation.
然后看 human gate 真的守住。首先,在 approve 前停下:
Have my agent request the right to act for me, then stop before I approve. Show me that it has nothing yet, no band, no access. Explain why "human in the loop" means the approval is the thing that mints the authority, not a formality after it.
接着证明这是 delegation,不是 impersonation:
Approve the grant, then show me the band. Point out where it says both the agent and that it is acting on behalf of me. Explain why that pairing matters for an audit trail.
刚刚发生了什么: agent 现在可以为你行动,但只有在你说 yes 之后,只在你批准的范围内,并且只到你 revoke 为止。它戴的是盖章手环,绝不是你的手环。
收紧手环:scope、value,以及危险事项的 fingerprint
盖章手环已经写着 drinks only。这个步骤用三个超出普通 scope string 的 ideas,让 limits 和 action 应得的限制一样紧。
capability 是 named action(agent 可以 share a note)。value-constraint 把它缩窄到允许的 values,不只是开或关:不是 "may share notes",而是 "may share notes only with @acme.com." scope string 表达不了这个;constraint 可以,并且 server 会在 agent 行动的那一刻检查,所以 share 给 @evil.com 会被拒绝,哪怕 capability 是 on。step-up approval 则把 human gate 随 blast radius 扩大:read 会 auto-grants,share 需要 logged-in human,不可逆 action(delete everything)需要物理存在,例如 fingerprint 或 passkey,这样一个恰好有 browser 的 AI agent 不能自己点击 approve 来批准自己的毁灭。这是图中的 over $50 needs Alice,只是那个真正危险的 action 需要 Alice 的 fingerprint,而不只是她一句 yes。粘贴:
Read
specs/projects/step-up-approval/spec.mdand.agents/skills/agent-identity-issuer/. Confirm the live agent-auth surface against the Better Auth docs MCP first, it is beta. Plan it, show me the plan, then build in small steps: three capabilities across the approval ladder (auto, session, physical-presence), one with a required value-constraint, and a single-use grant. Run every acceptance check, including the adversarial ones.
现在证明每个 limit 都会咬住。首先,value-constraint:
Give my agent the right to share notes, but only with
@acme.com. Then have it try to share with@evil.comand show me exactly where the server refuses it. Explain why a value-constraint is stronger than an on-or-off scope.
然后是危险 action 上的 step-up gate:
Try to approve the "delete everything" capability for my agent with just my logged-in session. Show me the server demanding physical presence instead of granting it, and explain what that step-up protects against when the agent itself has a browser.
刚刚发生了什么: agent 的手环现在和工作一样窄:限定到 capability,固定到允许 values,并且 action 越危险,gate 越硬;不可逆 action 锁在人类 fingerprint 后面。
关于成熟度的说明:为什么这是诚实,不是 hype
这门课教你锚定在 durable primitives 上,也就是 tooling churn 时仍然成立的部分:verified sign-in、agent 自己的 credential、on-behalf-of delegation、least-privilege scope 和 human approval。然后它会清楚说明每一层有多稳定:
- stable spine 今天就是 production-grade。 Sign-in、issuer、scopes and consent、连接 real app 和 resource server,都运行在成熟的 open-source Better Auth stack 上。整条 spine 加上 CIMD 已经在 1.7 line 上 live verified,Connector-Native Apps gateway 也接受了这个 issuer 签发的 tokens。前半部分是你可以 ship 的东西。
- CIMD 是 edge。 它能工作,也已 pin 和 prove,但它位于 Better Auth pre-release 和 IETF draft standard 上。预期它会移动;构建前重新确认 API。
- agent identity 是 frontier。 给 agent 自己 bounded、revocable、on-behalf-of authority,是行业正在走向的方向。Anthropic 用 human-agent teams 发出了信号,Better Auth 也有早期 Agent Auth plugin,但 standards 仍年轻,还在稳定。
这种拆分正是锚定 primitives 的意义。等 standards 落地时,mental model 已经适配:credential 仍是手环,scope 仍是手环允许你做什么,expiry 仍是 closing time,human approval 仍是柜台前那个人说 yes。
这会通向哪里
现在你已经有了整个 identity layer 的 through-line。把任何系统拿到一个问题前:这是谁的 identity,authority 又如何从 human 传给 agent,你就能读懂它:找出门口、柜台、手环和调酒师,然后问 agent 是借用人类手环,还是带着自己的手环。
这是 Manufacturing path 其余部分下面的 credential layer。接下来,Build AI Agents 会给这个 agent 它的 loop,也就是决定如何使用你刚学会授予的 authority 的 reasoning 和 tools。然后在 Human-Agent Teams 中,你会让这个 identity 投入工作,把一份 agents roster 与人类一起运行,每个 agent 都有自己的手环,并且只拥有被授予的 authority。
你停止了借用 identity。从这里开始,你签发它。