Workday Is Buying Identity for AI Agents. Let's Build a Tiny Access Grant in TypeScript.
本文为原文前 6,000 字符的节选翻译,完整内容请查看原文。
Most companies already know how to onboard a person. There’s a start date. A manager. A laptop. A list of apps. There’s also a last day. Access is supposed to end there. Agents are joining the same companies now. They need email, the CRM, a repo, sometimes finance. Here’s the part I keep thinking about. Nobody files a ticket for a bot’s last day.
大多数公司都已经知道如何让员工入职。有入职日期、经理、笔记本电脑和应用列表。同样也有离职日期,访问权限理应在那时终止。现在,智能体(Agents)也加入了这些公司。它们需要电子邮件、CRM、代码仓库,有时还需要财务权限。我一直在思考这一点:没人会为机器人的“离职日”提交工单。
On October 13, 2026, Workday announced it has “signed a definitive agreement to acquire C1.ai, a leading agentic identity platform for people and agents.” Workday says C1.ai connects to the systems a business runs on, “from email and CRM to code repositories, finance systems, and cloud infrastructure.” The release puts the agent part plainly: Once registered, an agent can receive the access it needs, when it needs it, and lose that access immediately when its work or role ends.
2026年10月13日,Workday宣布已“签署最终协议,收购领先的智能体身份平台C1.ai,该平台服务于人类和智能体。”Workday表示,C1.ai能够连接企业运行的各类系统,“从电子邮件和CRM到代码仓库、财务系统和云基础设施。”新闻稿明确指出了智能体部分:一旦注册,智能体就能在需要时获得所需的访问权限,并在其工作或角色结束时立即失去这些权限。
C1.ai would build on the Workday Agent System of Record. Workday says that record “already gives companies one place to see and manage their agents.” C1.ai would go “beyond registering agents to also governing what they can access.” One more line from the release stuck with me: An agent that was retired last quarter shouldn’t still be able to get in.
C1.ai将建立在Workday智能体记录系统(Agent System of Record)之上。Workday称,该记录系统“已经为企业提供了一个查看和管理智能体的统一场所。”C1.ai将“不仅限于注册智能体,还将管理它们的访问权限。”新闻稿中还有一句话让我印象深刻:上季度已停用的智能体不应再能进入系统。
The deal hasn’t closed. Workday expects it to close in the fourth quarter of its fiscal year 2027, which ends January 31, 2027, subject to customary closing conditions. The same day, Workday made its Trusted Agent Platform headless. “Headless can’t mean lawless,” said CTO Gabe Monroy. It also announced a partnership with Anthropic where Claude and Sana agents talk over MCP, and “every action follows the customer’s existing permissions and audit controls in Workday.”
该交易尚未完成。Workday预计将在其2027财年第四季度(截至2027年1月31日)完成,具体取决于惯例成交条件。同一天,Workday将其“可信智能体平台”(Trusted Agent Platform)改为无头(headless)模式。首席技术官Gabe Monroy表示:“无头并不意味着无法无天。”该公司还宣布与Anthropic建立合作伙伴关系,Claude和Sana智能体将通过MCP进行通信,并且“每一个操作都遵循客户在Workday中现有的权限和审计控制。”
Three announcements. Same direction. The agent’s access should follow the agent’s lifecycle. I’ve been waiting for this one. On September 19, in The Computer Is Becoming an API for AI, I wrote a short timeline. One line said: 2027: Agents get identities. Dedicated accounts, credentials, budgets, permissions and audit trails become normal. A signed deal is not “normal” yet. But it’s the right direction.
三项公告,同一个方向。智能体的访问权限应遵循其生命周期。我一直在等待这一刻。9月19日,在《计算机正在成为AI的API》一文中,我写了一个简短的时间表。其中一行写道:2027年:智能体获得身份。专用账户、凭证、预算、权限和审计追踪成为常态。签署协议尚不代表“常态”,但这确实是正确的方向。
It’s also a question I run into building Roster, where AI employees get real tools and real access. So let’s build a tiny version. By the end, you’ll run one command: npx tsx access-grant.ts And watch an agent get registered, get scoped grants, get denied above its role, lose finance on a role change, hit an expired grant, and lose everything the moment it ends.
这也是我在构建Roster时遇到的问题,在Roster中,AI员工会获得真实的工具和真实的访问权限。所以,让我们构建一个微型版本。最终,你只需运行一条命令:npx tsx access-grant.ts,就能观察到一个智能体被注册、获得范围授权、因超出角色权限被拒绝、在角色变更时失去财务权限、遇到过期授权,并在生命周期结束时失去所有权限的过程。
This is my small model of the idea. It is not how Workday or C1.ai work inside. The agents, roles, systems, scopes and times are example inputs. Everything runs in memory with a fake clock.
这是我对这一理念的小型建模。它并非Workday或C1.ai内部的实际运作方式。其中的智能体、角色、系统、范围和时间均为示例输入。一切都在内存中运行,并配有一个虚拟时钟。
-
The Problem Most access today is a pile of separate decisions. Someone files a ticket. Someone approves it. An app gets a token. Then the work ends. The agent gets marked as retired somewhere. And the token keeps working. The C1.ai release frames the question well: organizations “need to know who and what has access, why they have it, and when to remove it.” Three questions. Who, why, and when. The first one is the easy one. The other two are where it gets hard.
-
问题所在 当今大多数访问权限都是一系列孤立决策的堆砌。有人提交工单,有人批准,应用获得令牌。然后工作结束了,智能体在某处被标记为已停用,但令牌却依然有效。C1.ai的新闻稿很好地概括了这个问题:组织“需要知道谁拥有访问权限、拥有什么权限、为什么拥有这些权限,以及何时撤销它们。”三个问题:谁、为什么、何时。第一个问题很简单,后两个问题才是难点。
Workday’s answer is to tie access to lifecycle events. In its words, “every new hire, job change, and exit is a Workday event.” So in our tiny version, access moves with three events: The agent is registered. The agent’s role changes. The agent ends. Plus one more: a grant can expire on its own. A grant without a reason and an end is just a door left open.
Workday的解决方案是将访问权限与生命周期事件挂钩。用他们的话说,“每一次新入职、职位变动和离职都是一个Workday事件。”因此,在我们的微型版本中,访问权限随三个事件而变动:智能体注册、智能体角色变更、智能体终止。此外还有一点:授权可以自动过期。没有理由且没有终止期限的授权,就像一扇敞开的大门。
-
Step 1: An Agent System of Record Save the following TypeScript blocks in order as
access-grant.ts. First, the shapes. -
第一步:智能体记录系统 请按顺序将以下TypeScript代码块保存为
access-grant.ts。首先是数据结构。
// tiny-access-grant: lifecycle-bound access for registered AI agents.
// A small model of the idea. Not how Workday or C1.ai work inside.
// Agents, roles, systems, scopes and times are example inputs. No network. No API key.
type System = "email" | "crm" | "repo" | "finance" | "cloud";
type Status = "active" | "ended";
interface Agent {
id: string;
owner: string; // the person accountable for this agent
role: string;
status: Status;
}
interface Grant {
agentId: string;
system: System;
scopes: string[];
reason: string;
grantedAt: number; // minutes since midnight on a fake clock
expiresAt?: number;
revokedAt?: number;
revokeReason?: string;
}
interface Decision {
allow: boolean;
reason: string;
}
interface AuditEvent {
at: string;
kind: "register" | "grant" | "reject" | "check" | "revoke" | "role" | "end";
agentId: string;
detail: string;
}
// The most each role may hold. A grant can be smaller, never bigger.
const ROLE_CEILING: Record<string, Partial<Record<System, string[]>>> = {
"sales-assistant": { email: ["read", "send"], crm: ["read", "update"] },
"revops-analyst": { crm: ["read"], finance: ["read"] },
"support-triage": { email: ["read"], crm: ["read"] },
};
const hhmm = (t: number) => `${String(Math.floor(t / 60)).padStart(2, "0")}:${String(t % 60).padStart(2, "0")}`;
Every agent has an owner. That’s the person accountable for it. Every grant has a reason. That answers “why do they have it?” expiresAt and revokedAt answer “when does it end?” ROLE_CEILING is the most a role can ever hold. A sales assistant can send email and update the CRM. It never touches finance. Now the record itself.
每个智能体都有一个所有者,即对其负责的人。每个授权都有一个理由,这回答了“为什么拥有权限?”的问题。expiresAt 和 revokedAt 则回答了“何时结束?”的问题。ROLE_CEILING 是每个角色所能拥有的权限上限。销售助理可以发送邮件并更新CRM,但绝不会触及财务系统。现在是记录系统本身。
// Step 1: the agent system of record
interface Store {
now: number;
agents: Map<string, Agent>;
grants: Grant[];
audit: AuditEvent[];
}
function newStore(start = 9 * 60): Store {
return { now: start, agents: new Map(), grants: [], audit: [] };
}
function log(s: Store, kind: AuditEvent["kind"], agentId: string, detail: string): void {
s.audit.push({ at: hhmm(s.now), kind, agentId, detail });
}
function register(s: Store, id: string, owner: string, role: string): Agent {
if (s.agents.has(id)) throw new Error(`${id} is already registered`);
if (!ROLE_CEIL