Workday가 AI 에이전트를 위한 신원 인증(Identity)을 구매하다: TypeScript로 간단한 접근 권한 부여 시스템 구축하기
요약
Workday가 AI 에이전트의 신원 인증(Identity) 관리를 위해 C1.ai를 인수하고, Anthropic과 파트너십을 맺는 등 강력한 움직임을 보였습니다. 이는 에이전트에게도 사람처럼 명확한 생명주기 기반 접근 권한 및 감사 통제가 필요하다는 점에 초점을 맞춥니다.
핵심 포인트
- AI 에이전트의 퇴사일(접근권 종료) 관리가 핵심 과제입니다.
- Workday는 C1.ai 인수를 통해 에이전트 시스템 오브 레코드 구축을 목표합니다.
- Anthropic과의 파트너십으로 추론 결과를 비즈니스 규칙 및 권한에 연결합니다.
- 에이전트는 전용 계정, 자격 증명, 감사 기록 등 신원 관리가 필수적입니다.
대부분의 기업은 이미 사람을 온보딩(onboard)하는 방법을 알고 있습니다.
입사일이 있고, 관리자가 있으며, 노트북이 있고, 앱 목록이 있습니다.
하지만 퇴사일도 있습니다. 이때 접근 권한이 종료되어야 합니다.
이제 에이전트들도 같은 회사에 합류하고 있습니다. 이들은 이메일, CRM, 코드 저장소(repo), 때로는 재무 시스템까지 필요로 합니다.
제가 계속 생각하는 부분이 바로 여기입니다.
봇의 퇴사일에 아무도 티켓을 발행하지 않습니다.
2026년 10월 13일, Workday는 "사람과 에이전트를 위한 선도적인 에이전트 식별 플랫폼인 C1.ai를 인수하기로 하는 최종 합의에 서명했다"고 발표했습니다. Workday에 따르면 C1.ai는 기업이 운영하는 시스템들, 즉 "이메일과 CRM부터 코드 저장소, 재무 시스템, 클라우드 인프라까지" 연결됩니다.
이번 발표는 에이전트 부분에 대해 명확히 제시합니다:
등록된 후, 에이전트는 필요할 때 필요한 접근 권한을 받을 수 있으며, 업무나 역할이 종료되면 즉시 해당 접근 권한을 잃게 됩니다.
C1.ai는 Workday의 에이전트 시스템 오브 레코드(Agent System of Record)를 기반으로 구축될 것입니다. Workday에 따르면 이 기록은 "기업들이 자신들의 에이전트를 보고 관리할 수 있는 단일 장소"를 이미 제공합니다.
C1.ai는 단순히 에이전트를 등록하는 것을 넘어, 그들이 무엇에 접근할 수 있는지까지 통제(governing)하는 영역으로 나아갈 것입니다.
발표문에서 특히 마음에 남았던 문장이 하나 있습니다:
지난 분기에 퇴역한 에이전트가 여전히 접속할 수 있어서는 안 됩니다.
이번 거래는 아직 완료되지 않았습니다. Workday는 이 거래가 회계연도 2027년 4분기(2027년 1월 31일 마감)에 일반적인 종결 조건에 따라 완료될 것으로 예상하고 있습니다.
같은 날, Workday는 신뢰할 수 있는 에이전트 플랫폼을 헤드리스 방식으로 출시했습니다. CTO인 Gabe Monroy는 "헤드리스라는 것이 무법을 의미할 수는 없다"고 말했습니다.
또한, Workday는 Anthropic과의 파트너십도 발표했습니다 Anthropic과 Workday가 새로운 파트너십을 통해 추론(Reasoning)을 비즈니스를 운영하는 규칙에 연결합니다를 통해 Claude와 Sana 에이전트가 MCP(Master Control Plan?) 위에서 대화하며, "모든 동작은 Workday의 고객 기존 권한 및 감사 통제(audit controls)를 따릅니다."라고 합니다.
세 가지 발표. 같은 방향입니다.
에이전트의 접근 권한은 에이전트의 생명주기(lifecycle)를 따라야 합니다.
저는 이 부분을 기다려왔습니다. 9월 19일, The Computer Is Becoming an API for AI에서 짧은 타임라인을 작성한 적이 있습니다. 한 줄에 다음과 같이 쓰여 있었습니다:
2027년: 에이전트가 신원(identities)을 갖게 됩니다. 전용 계정, 자격 증명, 예산, 권한 및 감사 기록은 일상이 될 것입니다.
공식적인 계약 체결은 아직 '일상'은 아닙니다. 하지만 올바른 방향입니다.
이것은 또한 Roster를 구축하면서 제가 마주치는 질문이기도 합니다. AI 직원이 실제 도구와 실제 접근 권한을 갖게 하는 것입니다.
그래서 아주 작은 버전을 만들어 보겠습니다.
끝나면, 다음과 같은 명령어를 실행하게 될 것입니다:
npx tsx access-grant.ts
그리고 에이전트가 등록되고, 범위 지정된 권한(scoped grants)을 받고, 역할보다 높은 곳에서 거부되며, 역할 변경 시 재정적 손실을 겪고, 만료된 권한에 부딪히며, 끝나는 순간 모든 것을 잃는 모습을 지켜보게 될 것입니다.
이것은 제가 생각하는 아이디어의 작은 모델입니다. Workday나 C1.ai 내부에서 작동하는 방식은 아닙니다.
에이전트, 역할(roles), 시스템, 범위(scopes) 및 시간은 예시 입력값입니다. 모든 것은 가짜 시계와 함께 메모리 내에서 실행됩니다.
목차
- 문제점 (The Problem)
- 1단계: 에이전트의 기록 저장소 시스템 (An Agent System of Record)
- 2단계: 역할 내에 존재하는 권한 부여 (Grants That Live Inside the Role)
- 3단계: 모든 동작을 확인하기 (Check on Every Action)
- 4단계: 생명주기 이벤트가 접근 권한을 이동시키다 (Lifecycle Events Move Access)
- 5단계: 티켓 버전 (The Ticket Version)
- 6단계: 실행해보기 (Run It)
- 작동이 멈추는 곳 (Where It Breaks Down)
- 더 큰 아이디어 (The Bigger Idea)
1. 문제점 (The Problem)
오늘날 대부분의 접근 권한은 분리된 결정들의 더미에 불과합니다.
누군가 티켓을 제출합니다. 누군가가 승인합니다. 앱이 토큰을 받습니다.
그리고 작업이 끝납니다. 에이전트는 어딘가에서 은퇴 처리됩니다.
하지만 토큰은 계속 작동합니다.
C1.ai의 발표는 이 질문을 잘 제기합니다: 조직은 '누가, 무엇에 접근할 수 있는지, 왜 접근하는지, 그리고 언제 제거해야 하는지'를 알아야 합니다.'
세 가지 질문입니다. 누가(Who), 왜(Why), 그리고 언제(When).
첫 번째는 쉬운 문제입니다. 나머지 두 가지가 어려운 부분입니다.
Workday의 답변은 접근 권한을 라이프사이클 이벤트에 연결하는 것입니다. 그들의 말에 따르면, '새로운 채용, 직무 변경, 퇴사는 모두 Workday 이벤트입니다.'
따라서 저희의 작은 버전에서는 접근이 세 가지 이벤트와 함께 움직입니다:
- 에이전트가 등록됨.
- 에이전트의 역할(role)이 변경됨.
- 에이전트가 종료됨.
여기에 하나 더 추가됩니다: 부여된 권한(grant)은 스스로 만료될 수 있습니다.
이유와 끝이 없는 부여된 권한은 그저 열려 있는 문일 뿐입니다.
2. 단계 1: 에이전트 시스템의 기록원 (Agent System of Record)
다음 TypeScript 블록들을 순서대로 access-grant.ts로 저장하세요.
먼저, 구조체(shapes)들입니다.
// tiny-access-grant: 등록된 AI 에이전트를 위한 라이프사이클 기반 접근 권한.
// 아이디어를 보여주는 작은 모델일 뿐이며, Workday나 C1.ai 내부 작동 방식은 아닙니다.
// 에이전트, 역할, 시스템, 범위(scopes), 시간은 예시 입력값입니다. 네트워크 연결이나 API 키는 없습니다.
...
모든 에이전트는 소유자(owner)가 있습니다. 이 사람이 책임지는 사람입니다.
모든 부여된 권한에는 이유(reason)가 있습니다. 이것이 '왜 접근하는지'에 답합니다.
expiresAt과 revokedAt은 '언제 끝나는지'에 답합니다.
ROLE_CEILING은 역할이 가질 수 있는 최대치입니다. 영업 보조원은 이메일을 보내고 CRM을 업데이트할 수 있지만, 재무(finance)에는 절대 접근하지 않습니다.
이제 기록원 자체를 보겠습니다.
// Step 1: 에이전트 시스템의 기록원
interface Store {
now: number;
...
register만이 유일한 진입 경로입니다.
기록원에 없는 에이전트는 권한을 얻을 수 없습니다. 검증(check)을 통과할 수도 없습니다.
등록되어 있지 않다면, 존재하지 않는 것입니다.
3. 단계 2: 역할 내부에 존재하는 부여된 권한 (Grants That Live Inside the Role)
// Step 2: 역할 내부에 존재하는 부여된 권한
function isLive(g: Grant, now: number): boolean {
return g.revokedAt === undefined && (g.expiresAt === undefined || now < g.expiresAt);
...
부여된 권한은 네 가지 이유로 거부될 수 있습니다. 에이전트가 등록되지 않았거나, 에이전트가 종료되었거나, 이유가 없거나, 또는 범위(scopes)가 역할을 초과했기 때문입니다.
가장 중요한 부분은 상한선(ceiling check) 확인입니다.
호출자(caller)는 역할(role)이 허용하는 것보다 적게 요청할 수 있습니다. 더 많이 요청할 수는 없습니다.
동일 시스템에 대한 새로운 권한 부여(grant)가 이전 것을 대체합니다. 이전 것은 사유와 함께 로그에서 취소됩니다.
ttlMinutes는 권한 부여에 시간 제한을 둡니다. 이것이 바로 '언제 필요한지'를 나타내는 부분입니다.
4. 단계 3: 모든 액션마다 확인하기
// Step 3: 모든 액션에서 확인
function checkAccess(s: Store, agentId: string, system: System, action: string): Decision {
const d = decide(s, agentId, system, action);
...
순서가 중요합니다.
첫째, 이 에이전트가 기록에 있습니까? 다음으로, 여전히 활성화되어 있습니까? 그다음, 유효한 권한 부여가 있습니까? 마지막으로, 그 권한 부여가 이 액션을 포함합니까?
거부 사유(deny reasons)는 의도적으로 구체적입니다.
'재무 관련 권한 없음(No finance grant)'은 '09:45에 취소됨, 역할 변경됨'과는 다른 문제입니다.
'11:00 만료됨(Expired at 11:00)'은 또 다릅니다. 나중에 디버깅하는 사람이 어떤 경우인지 알아야 합니다.
허용되었든 아니든 모든 확인 과정은 감사 로그(audit log)에 기록됩니다.
5. 단계 4: 생명주기 이벤트가 접근 권한을 이동시키다
// Step 4: 생명주기 이벤트로 접근 권한 변경
function changeRole(s: Store, agentId: string, role: string): void {
const agent = s.agents.get(agentId);
...
이것이 핵심입니다.
changeRole은 모든 유효한 권한 부여를 순회하며 이를 새로운 상한선과 비교합니다.
만약 어떤 권한 부여가 새 역할이 가질 수 없는 범위(scopes)를 가지고 있다면, 그것은 취소됩니다. 여전히 허용되는 것은 동일한 만료 기한을 가지고 잘라내어 재권한 부여됩니다.
endAgent는 한 번의 호출로 두 가지 일을 합니다. 에이전트가 종료되었음을 표시합니다. 그리고 모든 유효한 권한 부여를 취소합니다.
두 번째 부분이 사람들이 건너뛰는 부분입니다.
에이전트를 종료하고 그 접근 권한을 종료하는 것은 동일한 이벤트여야 합니다.

6. 단계 5: 티켓 버전
우리 대부분이 시작하는 버전을 확인하려면 다음을 보세요.
// Step 5: 티켓 버전과 현재 접근 권한을 가진 사람
// 다운스트림 앱은 부여된 권한(grants)만 볼 뿐, 시스템 오브 레코드(system of record)에 직접 문의하지 않습니다.
function appSees(s: Store, agentId: string, system: System, action: string): boolean {
...
}
appSees는 다운스트림 앱이 아는 정보입니다. 이메일 앱은 요청할 때마다 시스템 오브 레코드에 호출하지 않습니다. 단지 부여된 권한(grant)이나 토큰을 보고 그것으로 충분합니다.
endInRecordOnly는 티켓 세계의 방식입니다. 에이전트가 한 곳에서 종료되었다고 표시됩니다. 하지만 접근 권한은 다른 곳에 존재할 수 있습니다.
whoHasAccess는 릴리스(release)가 던지는 질문에 직접 답합니다. 누가, 어떤 시스템을, 어떤 범위로, 언제까지, 그리고 왜 접근 가능한지 말입니다.
7. Step 6: 실행하기
// Step 6: 실행하기
function show(s: Store, agentId: string, system: System, action: string): void {
const d = checkAccess(s, agentId, system, action);
...
}
설치 및 실행:
npm install
npx tsx access-grant.ts
출력:
== 등록 및 부여 ==
09:00 부여(grant) email [read,send]: 초안 Q4 파이프라인 후속 조치
09:00 부여(grant) crm [read,update] 11:00까지: 후속 조치에서 호출된 로그 기록
...
무슨 일이 일어났는지 설명합니다.
pipeline-bot은 finance와 CRM delete에 대한 권한을 요청했습니다. 둘 다 해당 역할(role)보다 상위였기 때문에, 부여 시점에 모두 거부되었습니다.
09:05에는 이메일을 보내고 CR을 업데이트할 수 있었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기