Overview
You may want Devin to query a database while it debugs or answers a question. A shared database password in the Devin environment would give every session standing access, with no record of who asked for it. With Formal, Devin authenticates with its own short-lived OIDC token. Formal maps the token to a machine user and to the human who started the session. A blocks the machine user by default. When Devin needs data, it requests access, and the requester approves it in Slack. The approval suspends the block for that requester and Devin session only, and expires after the requested duration.Prerequisites
- A Postgres behind a Formal listener that the Devin VM can reach
- A Slack integration in Integrations, with every Devin user in your Slack workspace
- A Formal user for every Devin user, with the same email address
- Permission to create machine users, OIDC integrations, Permissions, policies, and workflows in Formal
- Permission to edit your Devin environment
Create the machine users
Go to Users and create two machine users:
Copy both
user_... IDs. Keep the workflow actor separate from Devin, so
Devin can never create its own suspension.
Configure the OIDC integration
Go to OIDC Integrations and click Create Integration. Select the Devin preset and thedevin machine
user.
1
Restrict the claim condition
Replace See Devin’s OIDC documentation
for all available claims.
your-org-id in the preset claim condition with your Devin
organization ID:2
Map the session requester
Keep the preset End-User Email Expression:Formal resolves this email to a Formal user when Devin mints a federation
token. The Connector then logs and evaluates each session with that person
as the .
3
Copy the audience
Copy the generated audience,
oidc.formal.ai/integrationoidc_.... Devin
requests OIDC tokens for this audience.Restrict Control Plane access
Devin only needs to request access and mint federation tokens. The workflow actor only needs to create policy suspensions. Go to Permissions, click Create Permission, name itdevin-database-access, and paste:
Block Devin by default
Go to Policies, click Create Policy, name itdevin-default-block, and paste:
policy_... ID. Approved access
still goes through your other policies, so masking and read-only rules keep
applying to Devin.
Create the approval workflow
Go to Workflows, click Create Workflow, name itdevin-database-access, and paste:
workflow_... ID.
The suspension condition uses only verified token claims: the requester’s
email and the Devin session (devin_id). Never interpolate payload fields into
input_condition, since Devin controls the payload and could inject CEL. Devin
chooses the reason and duration, and the approver sees both before approving.
A new Devin session needs a new approval.
Configure the Devin environment
1
Install the OIDC helper and clients
Add these steps to the The action installs the
initialize section of your
environment blueprint:devin-oidc CLI, which exchanges the session
token for an audience-scoped OIDC token.2
Reach the Connector
The Devin VM must reach the Connector listener. If the Connector is on a
private network, connect the VM to it, for example with a Tailscale subnet
router.
3
Add the access script
Commit Replace the placeholders. If the listener serves more than one resource,
set
scripts/formal-db.sh to the repository Devin works in:<DATABASE> to <DATABASE>@<RESOURCE_NAME>.The script mints a new federation token for each connection. Devin OIDC
tokens are short-lived, and a federation token never outlives the OIDC
token it came from.4
Tell Devin how to use it
Add instructions like these to Devin, for example as
Knowledge:
Verify the setup
Start a new Devin session and ask it to run:Devin is blocked by default; request JIT access. Then run:
SELECT 1 again. It should return one row.
Open Logs. The session should show the devin
machine user, your email as the end user, and the Devin claims under
user.oidc.claims. The suspension appears in
Policy Suspensions until it
expires.
Troubleshooting
Formal API calls return 401
Formal API calls return 401
Confirm the integration is Active and its issuer is
https://app.devin.ai. Confirm the script’s audience matches the
integration audience exactly. Confirm the token’s org_id matches the
claim condition.The workflow returns triggered: false
The workflow returns triggered: false
The
allow expression rejected the caller. Confirm the machine user ID in
the expression is the integration’s machine user.CreateFederationToken returns failed precondition
CreateFederationToken returns failed precondition
The requester’s email has no matching Formal user. Create the Formal user
or fix the email, then retry.
The connection is still blocked after approval
The connection is still blocked after approval
Check that the workflow run created a suspension. The suspension covers
only the requesting Devin session, so a new session needs a new request.
Next steps
OIDC Integrations
Configure claims and federated access
Workflows
Build other approval flows
Policy Suspensions
Review and revoke approved access
Block Agent Auto-Merge
Govern Devin’s GitHub access with the Formal Endpoint