Skip to content

[PoC] code chain grant implementation + agent chat example#153

Open
patatoid wants to merge 33 commits into
masterfrom
poc-agent-authorization
Open

[PoC] code chain grant implementation + agent chat example#153
patatoid wants to merge 33 commits into
masterfrom
poc-agent-authorization

Conversation

@patatoid
Copy link
Copy Markdown
Contributor

@patatoid patatoid commented May 11, 2026

Mixed Authentication Model

This example highlights that the same authorization chain can combine different kinds of actors and proofs while keeping an auditable code chain:

  • Wallet authentication: the initial browser-backed id_token presentation proves control of a wallet credential and creates the first authorization code in the chain.
  • User authentication: the later browser authorization_code request brings a normal user-facing OAuth authorization step into the same chain.
  • Machine authentication: each agent-to-agent handoff uses a machine-signed RS512 id_token with grant_type=code_chain, allowing non-human agents to advance the chain.

Scopes can also be requested and authorized at each level of the chain. A wallet-backed step can authorize credential-related scopes, a user-facing browser step can authorize user scopes, and a machine handoff can request scopes for the receiving agent’s responsibilities. The authorization codes produced at those steps can then be exchanged for access tokens or a verifiable credentials associated with the corresponding actor, proof, and authorized scopes.

Each step consumes the previous authorization code and produces the next one, so the workflow remains linked from the wallet-originated proof, through user authorization, through machine-to-machine agent handoffs. This keeps the full mixed-authentication workflow traceable as one auditable chain instead of splitting it into separate flows.

Summary

Adds a browser-bootstrapped agent chat example that demonstrates Boruta’s authorization code chain across a multi-agent workflow, with a mixed id_token / authorization_code / code_chain pipeline.

The flow starts with a browser id_token presentation, continues through agent-to-agent code_chain handoffs, then inserts a browser authorization_code request before the final writer step.

  1. user -> planner

    • The planner receives the first message after a browser-backed id_token presentation.
    • The browser request uses response_type=id_token with the credential scope.
    • The callback listener captures the resulting authorization code.
    • This first code becomes the root of the agent code chain.
  2. planner -> researcher/security/implementer

    • The planner fans the task out to three parallel agents.
    • Each receiving agent signs an RS512 id_token containing its message.
    • The script submits that id_token with the sender’s latest authorization code using grant_type=code_chain.
    • Boruta returns the next authorization_code, making each handoff part of the chain.
  3. researcher/security/implementer -> merger -> critic

    • The parallel branch outputs are merged and reviewed.
    • These internal handoffs continue through the same code_chain pattern:
      • previous authorization_code
      • receiving agent’s signed id_token
      • next authorization_code returned by /oauth/token
  4. critic -> writer

    • Before final response generation, the writer is bootstrapped with a browser authorization_code request.
    • This request uses response_type=code and includes the previous chained code.
    • The final transcript and issued codes are printed to stdout.

How to run

Start Boruta locally, configure the example client, then run the script:

  1. start the server
docker compose up -d
  1. Configure the example client (quickstart) then add http://127.0.0.1:8765/oauth-callback as an authorized redirect uri

  2. run the script

python3 scripts/agent_chat.py

Example output

[browser -> first id_token presentation]
Opening http://localhost:8080/oauth/authorize?client_id=00000000-0000-0000-0000-000000000001&redirect_uri=http%3A%2F%2F127.0.0.1%3A8765%2Foauth-callback&response_type=id_token&prompt=login&scope=&state=agent-chat&client_metadata=%7B%7D
Complete the id_token presentation. Waiting for the final redirect code...
[id_token presentation -> planner]
CTP9izpGGWsd7riniVw2XP3o9FfjbCBq4sEE13yi3VyfqE2kp7IvSHImG7faxmXtkM2pW1K3PQDgQ8FzpAZo3l
{'authorization_code': 'iIltgPYNNTeurxJCdTuM4X10zMXpIX2XreQpQoaSXKIUEblqebEipaYn6ZsWGdKqeyDSuvATxvogwzxpDTxhob', 'c_nonce': None, 'expires_in': 600, 'refresh_token': None, 'token_type': 'bearer'}
[code_chain -> researcher]
iIltgPYNNTeurxJCdTuM4X10zMXpIX2XreQpQoaSXKIUEblqebEipaYn6ZsWGdKqeyDSuvATxvogwzxpDTxhob
{'authorization_code': 'uLyCwhW5ssmgHbWkrMVN3hAxPBWWZHUfOIyfweZWQM4gqdj3UKjE72LNGoDoU4rTsuvOxei4msvg7lKnQfop7l', 'c_nonce': None, 'expires_in': 600, 'refresh_token': None, 'token_type': 'bearer'}
[code_chain -> security]
uLyCwhW5ssmgHbWkrMVN3hAxPBWWZHUfOIyfweZWQM4gqdj3UKjE72LNGoDoU4rTsuvOxei4msvg7lKnQfop7l
{'authorization_code': 'w1jdpDaUQqO5Jys8Y3HMEj5Sf6G6jRC70o4k4oHOXnrz9rSpU6v3z6Oh7cAJR6i5DlQkF3GYd7SaQ0XcqKxKUY', 'c_nonce': None, 'expires_in': 600, 'refresh_token': None, 'token_type': 'bearer'}
[code_chain -> implementer]
w1jdpDaUQqO5Jys8Y3HMEj5Sf6G6jRC70o4k4oHOXnrz9rSpU6v3z6Oh7cAJR6i5DlQkF3GYd7SaQ0XcqKxKUY
{'authorization_code': '2pj2cWTam2vZgzDQZGF7W7PljbhqeUd00hHNtDMd3OMEOVr8VQD0D4ytWWp8s5qQHN9sy96gSVMmYZwLytZsQ4', 'c_nonce': None, 'expires_in': 600, 'refresh_token': None, 'token_type': 'bearer'}
[code_chain -> merger]
2pj2cWTam2vZgzDQZGF7W7PljbhqeUd00hHNtDMd3OMEOVr8VQD0D4ytWWp8s5qQHN9sy96gSVMmYZwLytZsQ4
{'authorization_code': '83DIb2iqvRKN6n3NVEl4QFRiBoGyYUYagJbs34KUFhsnODm1uS2DTCjTST481ecHohmBzCZKpfyW5SfcPEqD0x', 'c_nonce': None, 'expires_in': 600, 'refresh_token': None, 'token_type': 'bearer'}
[code_chain -> merger]
83DIb2iqvRKN6n3NVEl4QFRiBoGyYUYagJbs34KUFhsnODm1uS2DTCjTST481ecHohmBzCZKpfyW5SfcPEqD0x
{'authorization_code': 'ObhUyEy3SHkWbcaEemIdLSNBBFh82eSz9xt6um3USCQ02KooJG9SccQFoo9wW2Sh5V4WkaLuoVRqS6ikbUvvH4', 'c_nonce': None, 'expires_in': 600, 'refresh_token': None, 'token_type': 'bearer'}
[code_chain -> merger]
ObhUyEy3SHkWbcaEemIdLSNBBFh82eSz9xt6um3USCQ02KooJG9SccQFoo9wW2Sh5V4WkaLuoVRqS6ikbUvvH4
{'authorization_code': 'liniw4bcCwJ5R2gwOgQ9kERgCm9O1P4cqVaeK0kGB3DTSIREVeJbr3dwPf0qXsp7dcq289gporeM9s01e58zPu', 'c_nonce': None, 'expires_in': 600, 'refresh_token': None, 'token_type': 'bearer'}
[code_chain -> critic]
liniw4bcCwJ5R2gwOgQ9kERgCm9O1P4cqVaeK0kGB3DTSIREVeJbr3dwPf0qXsp7dcq289gporeM9s01e58zPu
[browser -> chained authorization code request]
Opening http://localhost:8080/oauth/authorize?client_id=00000000-0000-0000-0000-000000000001&redirect_uri=http%3A%2F%2F127.0.0.1%3A8765%2Foauth-callback&response_type=code&prompt=login&scope=email&state=agent-chat&code=liniw4bcCwJ5R2gwOgQ9kERgCm9O1P4cqVaeK0kGB3DTSIREVeJbr3dwPf0qXsp7dcq289gporeM9s01e58zPu
Complete the authorization code request. Waiting for the final redirect code...
[authorization code request -> writer]
GYFx1Qv9e28bACfZDvNv1stpLZIP3GNLtrxMuBNApfDnWEhlHHslKKkxCFd85O3LaW5xV7dspcs8gEfS0ILfsZ

Notes

  • The agent client key is generated automatically if missing.
  • The script prints each authorization code as it advances through the chain, which makes the handoff sequence easy to inspect.

@patatoid patatoid force-pushed the poc-agent-authorization branch 8 times, most recently from 7f97e4c to 335b105 Compare May 15, 2026 20:33
@patatoid patatoid force-pushed the poc-agent-authorization branch 20 times, most recently from e3d56b5 to 6b01936 Compare May 19, 2026 11:39
@patatoid patatoid force-pushed the poc-agent-authorization branch from d626aa1 to 4698af4 Compare May 29, 2026 03:38
@patatoid patatoid changed the title [POC] code chain grant implementation + agent chat example [PoC] code chain grant implementation + agent chat example May 29, 2026
@patatoid patatoid force-pushed the poc-agent-authorization branch from f02743c to c301488 Compare May 31, 2026 12:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant