Skip to content

feat: Add agent registration read and credential validation methods#1642

Open
m0tzy wants to merge 7 commits into
mainfrom
madison/initial-agent-methods
Open

feat: Add agent registration read and credential validation methods#1642
m0tzy wants to merge 7 commits into
mainfrom
madison/initial-agent-methods

Conversation

@m0tzy

@m0tzy m0tzy commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds two SDK methods for the new API-key-authenticated agent-auth endpoints introduced in workos/workos#63723, surfaced under workos.agents:

  • workos.agents.getRegistration(id)GET /agents/registrations/:id. Reads a single agent registration scoped to the API key's environment, returning its derived status/kind, agent identity, organization, and claim state.
  • workos.agents.validateCredential({ type, credential })POST /agents/credentials/validate. Validates an agent credential (api_key or access_token) and returns { valid, registrationId, expiresAt }. Read-only — it never consumes or mutates the credential.

The module follows the existing per-module layout (interfaces / serializers / fixtures / spec), deserializing the API's snake_case payloads into camelCase. It's wired into the WorkOS client (readonly agents) and re-exported from src/index.ts.

Notes

  • Hand-written, not generated by oagen. These endpoints are gated behind the server-side agent-auth-public-api flag and excluded from the public OpenAPI spec, so they won't appear in codegen yet. When they're eventually published to the spec, oagen may want to regenerate this module.
  • Calls will 404 against environments where agent-auth-public-api is not enabled — expected while the feature is flag-gated.

Testing

  • jest src/agents — 3 tests pass (registration read, valid credential, invalid credential)
  • tsc --noEmit, eslint, and prettier --check all clean
  • index.barrel spec passes

🤖 Generated with Claude Code

Closes AUTH-6622

m0tzy and others added 4 commits June 24, 2026 15:09
validateCredential now verifies access_token credentials against the
environment's cached JWKS and returns the decoded claims without a network
request. A new checkForRevoked option (access_token only) additionally calls
the server to confirm the token has not been revoked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tion result

Local access_token verification now enforces the token audience (defaulting to
the configured client ID, with an `audience` override for resource-scoped
tokens whose aud is the resource). The validation result is now a discriminated
union on `valid`, so a valid result narrows registrationId to a non-null string.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The validate endpoint now accepts an optional audience on the access_token
variant, so checkForRevoked requests forward the same audience the SDK verifies
against locally, letting the server verify the JWT aud claim too. The audience
option is narrowed to a single string to match the endpoint's contract.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@linear-code

linear-code Bot commented Jun 25, 2026

Copy link
Copy Markdown

AUTH-6622

Agent registration ids use the agent_reg_ prefix (not agent_registration_),
claims use agent_reg_claim_, and claim attempts use agent_reg_claim_attempt_.
Also exercise the non-null claim_completion path in the getRegistration test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@m0tzy m0tzy marked this pull request as ready for review June 25, 2026 20:25
@m0tzy m0tzy requested review from a team as code owners June 25, 2026 20:25
@m0tzy m0tzy requested a review from ericroberts June 25, 2026 20:25

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Open in Devin Review

Comment thread src/agents/agents.ts
@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds an agents SDK surface. The main changes are:

  • workos.agents.getRegistration(id) for registration reads.
  • workos.agents.validateCredential(...) for API keys and access tokens.
  • New agent interfaces, serializers, fixtures, and WorkOS wiring.

Confidence Score: 3/5

The new agents SDK surface is mostly covered, but the revocation-check merge path can return conflicting registration identities.

Endpoint wiring, serialization, local access-token validation, and mocked request behavior are exercised. The remaining concern is in the successful access-token revocation path, where the server verdict and local token claims are combined without confirming they refer to the same registration.

src/agents/agents.ts needs attention around the checkForRevoked path in validateAccessToken.

T-Rex T-Rex Logs

What T-Rex did

  • Ran the harness against commit e1cdb7f and observed a failure due to missing pre-PR dependency or surface setup.
  • Validated the post-PR API surface by confirming GET /agents/registrations/agent_reg%2F..%2F..%2Fevil returned 200 OK with camelCased registration and POST /agents/credentials/validate for api_key returned 200 OK with camelCased validation.
  • Verified the access_token flow: the local path made 0 HTTP requests, and the revocation path POSTed the credential plus audience and returned 200 OK.

View all artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
src/agents/agents.ts:120-121
**Remote Claims Can Diverge**

When `checkForRevoked` is enabled, this merge keeps the server's `registrationId` but attaches claims from the locally verified token without checking that both identify the same registration. If the validation API returns a valid response for a different registration than the JWT `sub`, callers receive two different identities in one successful result.

Reviews (4): Last reviewed commit: "refactor(agents): Require core access to..." | Re-trigger Greptile

Comment thread src/agents/agents.ts Outdated
Comment thread src/agents/serializers/validate-agent-credential.serializer.ts
Comment thread src/agents/agents.ts Outdated
- Reject access tokens missing the agent identity claims (sub/jti/
  organization_id) instead of reporting them valid with empty identifiers.
- Treat a valid server verdict with a null registration_id as invalid.
- URL-encode the registration id in the getRegistration request path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@m0tzy

m0tzy commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

Comment thread src/agents/agents.ts Outdated
Comment thread src/agents/agents.ts Outdated
…piry

Mark iss/aud/exp/iat (and sub/jti/organization_id) required on
SerializedAgentAccessTokenClaims and guarantee them via a single
hasRequiredAgentClaims guard, so decoded claims never surface empty values.
Also reject a token whose exp is in the past explicitly, and keep the raw
jti claim name instead of mapping it to jwtId.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread src/agents/agents.ts
Comment on lines +120 to +121
const remote = await this.validateCredentialRemotely(options);
return remote.valid ? { ...remote, claims } : remote;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Remote Claims Can Diverge

When checkForRevoked is enabled, this merge keeps the server's registrationId but attaches claims from the locally verified token without checking that both identify the same registration. If the validation API returns a valid response for a different registration than the JWT sub, callers receive two different identities in one successful result.

Rule Used: JWTs should always be validated before use and the... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/agents.ts
Line: 120-121

Comment:
**Remote Claims Can Diverge**

When `checkForRevoked` is enabled, this merge keeps the server's `registrationId` but attaches claims from the locally verified token without checking that both identify the same registration. If the validation API returns a valid response for a different registration than the JWT `sub`, callers receive two different identities in one successful result.

**Rule Used:** JWTs should always be validated before use and the... ([source](https://app.greptile.com/workos/-/custom-context?memory=e0f82177-2285-4c61-8843-a81dfdf8fd23))

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant