diff --git a/.changelog-pending/2026-09-01T21-42-41-b6350ef365d412ae1775ac389c8d8e4ad8c20734.md b/.changelog-pending/2026-09-01T21-42-41-b6350ef365d412ae1775ac389c8d8e4ad8c20734.md new file mode 100644 index 00000000..6956fd57 --- /dev/null +++ b/.changelog-pending/2026-09-01T21-42-41-b6350ef365d412ae1775ac389c8d8e4ad8c20734.md @@ -0,0 +1,9 @@ +* [#437](https://github.com/workos/workos-php/pull/437) fix(generated): regenerate from spec + + **Features** + * **[agents](https://workos.com/docs/reference/agents)**: + * Made `AgentBlueprintsCreateRequest.session_settings` optional + * Added model `AgentTokenValidation` + * Added model `AgentBlueprintsTokenValidateTokenRequest` + * **agents_blueprints_tokens**: + * Added endpoint `POST /agents/blueprints/{agent_blueprint_id}/tokens/validate` diff --git a/.last-synced-sha b/.last-synced-sha index 0f267924..d20a1099 100644 --- a/.last-synced-sha +++ b/.last-synced-sha @@ -1 +1 @@ -d61348070f219d16b6285f205986c2d332bf6e9c +edb560e2be3f54b668ea8d11fa5a060c87ab5087 diff --git a/.oagen-manifest.json b/.oagen-manifest.json index 7c753762..0c3c5de5 100644 --- a/.oagen-manifest.json +++ b/.oagen-manifest.json @@ -31,6 +31,7 @@ "lib/Resource/AgentBlueprintsCreateRequestSessionSetting.php", "lib/Resource/AgentBlueprintsTokenMintTokenRequest.php", "lib/Resource/AgentBlueprintsTokenMintTokenRequestType.php", + "lib/Resource/AgentBlueprintsTokenValidateTokenRequest.php", "lib/Resource/AgentBlueprintsUpdateRequest.php", "lib/Resource/AgentBlueprintsUpdateRequestInvocableBy.php", "lib/Resource/AgentBlueprintsUpdateRequestSessionSetting.php", @@ -75,6 +76,7 @@ "lib/Resource/AgentRegistrationRevokedData.php", "lib/Resource/AgentRegistrationStatus.php", "lib/Resource/AgentToken.php", + "lib/Resource/AgentTokenValidation.php", "lib/Resource/ApiKey.php", "lib/Resource/ApiKeyCreated.php", "lib/Resource/ApiKeyCreatedData.php", @@ -748,6 +750,7 @@ "tests/Fixtures/agent_blueprints_create_request_invocable_by.json", "tests/Fixtures/agent_blueprints_create_request_session_setting.json", "tests/Fixtures/agent_blueprints_token_mint_token_request.json", + "tests/Fixtures/agent_blueprints_token_validate_token_request.json", "tests/Fixtures/agent_blueprints_update_request.json", "tests/Fixtures/agent_blueprints_update_request_invocable_by.json", "tests/Fixtures/agent_blueprints_update_request_session_setting.json", @@ -788,6 +791,7 @@ "tests/Fixtures/agent_registration_revoked.json", "tests/Fixtures/agent_registration_revoked_data.json", "tests/Fixtures/agent_token.json", + "tests/Fixtures/agent_token_validation.json", "tests/Fixtures/api_key.json", "tests/Fixtures/api_key_created.json", "tests/Fixtures/api_key_created_data.json", @@ -2371,6 +2375,10 @@ "POST /user_management/waitlists/{id}/entries": { "sdkMethod": "createWaitlistEntry", "service": "userManagement" + }, + "POST /agents/blueprints/{agent_blueprint_id}/tokens/validate": { + "sdkMethod": "validateBlueprintToken", + "service": "agents" } } } diff --git a/lib/Resource/AgentBlueprintsCreateRequest.php b/lib/Resource/AgentBlueprintsCreateRequest.php index 35d8eccd..2e33b79e 100644 --- a/lib/Resource/AgentBlueprintsCreateRequest.php +++ b/lib/Resource/AgentBlueprintsCreateRequest.php @@ -13,8 +13,6 @@ public function __construct( /** Human-readable name of the agent blueprint. */ public string $name, - /** Token and session lifetimes for sessions minted from this blueprint. */ - public AgentBlueprintsCreateRequestSessionSetting $sessionSettings, /** Human-readable description of the agent blueprint. */ public ?string $description = null, /** @@ -24,6 +22,8 @@ public function __construct( public ?array $permissions = null, /** Who may mint sessions from this blueprint. */ public ?AgentBlueprintsCreateRequestInvocableBy $invocableBy = null, + /** Token and session lifetimes for sessions minted from this blueprint. */ + public ?AgentBlueprintsCreateRequestSessionSetting $sessionSettings = null, ) { } @@ -31,10 +31,10 @@ public static function fromArray(array $data): self { return new self( name: $data['name'], - sessionSettings: AgentBlueprintsCreateRequestSessionSetting::fromArray($data['session_settings']), description: $data['description'] ?? null, permissions: $data['permissions'] ?? null, invocableBy: isset($data['invocable_by']) ? AgentBlueprintsCreateRequestInvocableBy::fromArray($data['invocable_by']) : null, + sessionSettings: isset($data['session_settings']) ? AgentBlueprintsCreateRequestSessionSetting::fromArray($data['session_settings']) : null, ); } @@ -42,10 +42,10 @@ public function toArray(): array { return [ 'name' => $this->name, - 'session_settings' => $this->sessionSettings->toArray(), 'description' => $this->description, 'permissions' => $this->permissions, 'invocable_by' => $this->invocableBy?->toArray(), + 'session_settings' => $this->sessionSettings?->toArray(), ]; } } diff --git a/lib/Resource/AgentBlueprintsTokenValidateTokenRequest.php b/lib/Resource/AgentBlueprintsTokenValidateTokenRequest.php new file mode 100644 index 00000000..4e7df9e6 --- /dev/null +++ b/lib/Resource/AgentBlueprintsTokenValidateTokenRequest.php @@ -0,0 +1,32 @@ + $this->agentAccessToken, + ]; + } +} diff --git a/lib/Resource/AgentTokenValidation.php b/lib/Resource/AgentTokenValidation.php new file mode 100644 index 00000000..ddab144a --- /dev/null +++ b/lib/Resource/AgentTokenValidation.php @@ -0,0 +1,63 @@ + + */ + public array $permissions, + /** The caller-supplied context echoed into the token at mint time, or `null` when none was given. */ + public ?string $intent, + /** The delegating user carried in the `act.sub` claim of the token, or `null` for autonomous sessions. */ + public ?string $actingUserId, + /** When the backing agent instance session expires. */ + public string $sessionExpiresAt, + ) { + } + + public static function fromArray(array $data): self + { + return new self( + valid: $data['valid'] ?? true, + agentInstanceId: $data['agent_instance_id'], + agentInstanceSessionId: $data['agent_instance_session_id'], + organizationId: $data['organization_id'], + permissions: $data['permissions'], + intent: $data['intent'] ?? null, + actingUserId: $data['acting_user_id'] ?? null, + sessionExpiresAt: $data['session_expires_at'], + ); + } + + public function toArray(): array + { + return [ + 'valid' => $this->valid, + 'agent_instance_id' => $this->agentInstanceId, + 'agent_instance_session_id' => $this->agentInstanceSessionId, + 'organization_id' => $this->organizationId, + 'permissions' => $this->permissions, + 'intent' => $this->intent, + 'acting_user_id' => $this->actingUserId, + 'session_expires_at' => $this->sessionExpiresAt, + ]; + } +} diff --git a/lib/Service/Agents.php b/lib/Service/Agents.php index 91cce02a..eb486c52 100644 --- a/lib/Service/Agents.php +++ b/lib/Service/Agents.php @@ -12,6 +12,7 @@ use WorkOS\Resource\AgentInstanceSession; use WorkOS\Resource\AgentRegistration; use WorkOS\Resource\AgentToken; +use WorkOS\Resource\AgentTokenValidation; use WorkOS\Resource\ClaimViewResponse; class Agents @@ -62,16 +63,16 @@ public function listBlueprints( * @param string|null $description Human-readable description of the agent blueprint. * @param array|null $permissions Permission slugs forming the ceiling on what sessions minted from this blueprint may do. Each slug must exist in the environment. * @param \WorkOS\Resource\AgentBlueprintsCreateRequestInvocableBy|null $invocableBy Who may mint sessions from this blueprint. - * @param \WorkOS\Resource\AgentBlueprintsCreateRequestSessionSetting $sessionSettings Token and session lifetimes for sessions minted from this blueprint. + * @param \WorkOS\Resource\AgentBlueprintsCreateRequestSessionSetting|null $sessionSettings Token and session lifetimes for sessions minted from this blueprint. * @return \WorkOS\Resource\AgentBlueprint * @throws \WorkOS\Exception\WorkOSException */ public function createBlueprint( string $name, - \WorkOS\Resource\AgentBlueprintsCreateRequestSessionSetting $sessionSettings, ?string $description = null, ?array $permissions = null, ?\WorkOS\Resource\AgentBlueprintsCreateRequestInvocableBy $invocableBy = null, + ?\WorkOS\Resource\AgentBlueprintsCreateRequestSessionSetting $sessionSettings = null, ?\WorkOS\RequestOptions $options = null, ): \WorkOS\Resource\AgentBlueprint { $body = array_filter([ @@ -208,6 +209,32 @@ public function createBlueprintToken( return AgentToken::fromArray($response); } + /** + * Validate an agent token + * + * Validates an agent access token: verifies its signature against the environment, that it was minted under this blueprint, and that the backing session is live (not revoked or expired, and — for delegated sessions — that the delegating user session has not ended). Returns the token claims and session metadata when valid; invalid tokens are reported as errors with stable codes. + * @param string $agentBlueprintId The unique ID of the agent blueprint. + * @param string $agentAccessToken The agent access token (a JWT) to validate. + * @return \WorkOS\Resource\AgentTokenValidation + * @throws \WorkOS\Exception\WorkOSException + */ + public function validateBlueprintToken( + string $agentBlueprintId, + string $agentAccessToken, + ?\WorkOS\RequestOptions $options = null, + ): \WorkOS\Resource\AgentTokenValidation { + $body = [ + 'agent_access_token' => $agentAccessToken, + ]; + $response = $this->client->request( + method: 'POST', + path: 'agents/blueprints/' . rawurlencode($agentBlueprintId) . '/tokens/validate', + body: $body, + options: $options, + ); + return AgentTokenValidation::fromArray($response); + } + /** * Link a claim attempt to an external user * diff --git a/tests/Fixtures/agent_blueprints_token_validate_token_request.json b/tests/Fixtures/agent_blueprints_token_validate_token_request.json new file mode 100644 index 00000000..4de2ff44 --- /dev/null +++ b/tests/Fixtures/agent_blueprints_token_validate_token_request.json @@ -0,0 +1,3 @@ +{ + "agent_access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6..." +} diff --git a/tests/Fixtures/agent_token_validation.json b/tests/Fixtures/agent_token_validation.json new file mode 100644 index 00000000..2d6d5e2c --- /dev/null +++ b/tests/Fixtures/agent_token_validation.json @@ -0,0 +1,12 @@ +{ + "valid": true, + "agent_instance_id": "agent_01EHWNCE74X7JSDV0X3SZ3KJNY", + "agent_instance_session_id": "agent_session_01EHWNCE74X7JSDV0X3SZ3KJNY", + "organization_id": "org_01EHWNCE74X7JSDV0X3SZ3KJNY", + "permissions": [ + "crm:read" + ], + "intent": "renew-contract-123", + "acting_user_id": "userland_user_01EHWNCE74X7JSDV0X3SZ3KJNY", + "session_expires_at": "2024-01-01T00:00:00.000Z" +} diff --git a/tests/Service/AgentsTest.php b/tests/Service/AgentsTest.php index cce51071..2e3a08d3 100644 --- a/tests/Service/AgentsTest.php +++ b/tests/Service/AgentsTest.php @@ -33,7 +33,7 @@ public function testCreateBlueprint(): void { $fixture = $this->loadFixture('agent_blueprint'); $client = $this->createMockClient([['status' => 200, 'body' => $fixture]]); - $result = $client->agents()->createBlueprint(name: 'test_value', sessionSettings: \WorkOS\Resource\AgentBlueprintsCreateRequestSessionSetting::fromArray($this->loadFixture('agent_blueprints_create_request_session_setting'))); + $result = $client->agents()->createBlueprint(name: 'test_value'); $this->assertInstanceOf(\WorkOS\Resource\AgentBlueprint::class, $result); $this->assertSame($fixture['id'], $result->id); $this->assertSame($fixture['name'], $result->name); @@ -95,6 +95,21 @@ public function testCreateBlueprintToken(): void $this->assertStringEndsWith('agents/blueprints/test_agent_blueprint_id/tokens', $request->getUri()->getPath()); } + public function testValidateBlueprintToken(): void + { + $fixture = $this->loadFixture('agent_token_validation'); + $client = $this->createMockClient([['status' => 200, 'body' => $fixture]]); + $result = $client->agents()->validateBlueprintToken('test_agent_blueprint_id', agentAccessToken: 'test_value'); + $this->assertInstanceOf(\WorkOS\Resource\AgentTokenValidation::class, $result); + $this->assertSame($fixture['agent_instance_id'], $result->agentInstanceId); + $this->assertIsArray($result->toArray()); + $request = $this->getLastRequest(); + $this->assertSame('POST', $request->getMethod()); + $this->assertStringEndsWith('agents/blueprints/test_agent_blueprint_id/tokens/validate', $request->getUri()->getPath()); + $body = json_decode((string) $request->getBody(), true); + $this->assertSame('test_value', $body['agent_access_token']); + } + public function testUpdateAttempts(): void { $fixture = $this->loadFixture('claim_view_response');