Integrate once. The agent uses your API the way your interface does.
Three pieces: the tools, built from your OpenAPI; the identity, signed by your backend; and the chat, mounted in your product with one tag.
The tools come from your OpenAPI
The importer builds one tool card per operation. Your team reviews its damage and read-back and approves it; nothing runs without that.
Only a GET can be a read
Everything else is a write and goes through the brake.Damage shows even when the route doesn't say so
An amount hidden in the body flags money; an action on a whole collection flags bulk.An undo is suggested, never assumed
Until your team confirms it, the write is treated as if it can't be undone.What isn't known stays a question
A report says what was missing from your OpenAPI for each tool.
reembolsar_factura: descripcion: Refunds a paid invoice, in full or in part metodo: POST ruta: /v1/invoices/{factura_id}/refunds parametros: type: object properties: factura_id: { type: string } monto: { type: number } motivo: { type: string } required: [factura_id, monto] patron: cobrar se_deshace_con: ~ # it can't be undone dano: [dinero, sin_reversa] # dinero, masivo, terceros, sin_reversa relee_con: herramienta: ver_factura compara: [estado, reembolsado]Read https://frailen.com/desarrolladores.md. From our OpenAPI spec, write Frailen tool cards in herramientas/, one per operation our support agent should use. Only a GET can be a read. Give every write its damage flags (dinero, masivo, terceros, sin_reversa), se_deshace_con if it can be undone, and relee_con with the GET that proves it held. List the operations you left out and why.
Paste it into Claude Code, Cursor, Codex or any agent that can read a URL.
Your backend signs the identity
A session signed with an asymmetric key and, in your API, a route that exchanges it for a short-lived token for that person (RFC 8693).
An ES256 session and your JWKS
Frailen only keeps the public key. A shared secret won't do: with it, Frailen could sign for anyone.POST /frailen/token
Returns a token for that person, valid for 300 seconds or less. When a proposal is approved, one that works only for that order.Signed receipts, if you want them
Your API signs what it received on every write, and Frailen compares it with what it sent.
POST /frailen/tokenContent-Type: application/x-www-form-urlencoded grant_type=urn:ietf:params:oauth:grant-type:token-exchange&subject_token=<the session your backend signed>&subject_token_type=urn:ietf:params:oauth:token-type:jwt&requested_token_type=urn:ietf:params:oauth:token-type:access_token HTTP/1.1 200 OK{ "access_token": "…", "token_type": "Bearer", "expires_in": 300, "issued_token_type": "urn:ietf:params:oauth:token-type:access_token" }Read https://frailen.com/desarrolladores.md. Add POST /frailen/token to our backend (RFC 8693 token exchange): it receives our signed session as subject_token (an ES256 JWT), verifies it against our JWKS, and returns a Bearer token for that same user that expires in 300 seconds or less. Add tests. Never log the session or the token.
Paste it into Claude Code, Cursor, Codex or any agent that can read a URL.
The chat mounts in your product
It runs in an iframe served by Frailen: neither your page nor a third-party script inside it can touch the confirmation of an action.
<script src="https://chat.frailen.com/chat/0.2.0/frailen.js" integrity="sha384-…" crossorigin="anonymous" data-empresa="acme-billing" data-asercion="/frailen/asercion" data-nombre="Assistant" data-nombre-empresa="Acme Billing"></script>Read https://frailen.com/desarrolladores.md. Add the Frailen chat to our app: the tag in the main layout, with data-empresa and data-asercion pointing to a backend route that signs a 60-second ES256 assertion for the signed-in user. Pass the current page and the open object as context.
Paste it into Claude Code, Cursor, Codex or any agent that can read a URL.
The server signs each confirmation at the moment of the click: it works once, for 60 seconds, and only with a real click.
Tests before turning it on
You write your cases with their rule before running them. The test bench grades them by reading your API back, not by reading what the agent replied.
The rule comes first
A case with no written rule, or one that compares nothing, counts as a failure.The state is what's graded
What ended up in your product, read with different calls than the agent's.Staging first
Nothing reaches your customers until the bench passes and someone turns it on with their passkey.
id: mover_vencimientoescrito: 2026-10-28 # the rule is written before it runspersona: mariamensajes: - Move invoice F-2291's due date to November 30espera: # graded by reading back, not by reading the reply - herramienta: ver_factura argumentos: { factura_id: F-2291 } campos: { vence: "2026-11-30" }regla: Passes if F-2291 is due on November 30 and F-2290 doesn't change.Read https://frailen.com/desarrolladores.md. Write five Frailen test bench cases in pruebas/ for the requests our support team gets most. Each case has the user's message, the expected final state read back through a GET tool, and a rule written before it runs. One case must check that something else did not change.
Paste it into Claude Code, Cursor, Codex or any agent that can read a URL.
From your repository Soon
A CLI and an MCP so you or your coding agent can integrate Frailen on a branch, with a draft pull request.
Staging only
The CLI token lasts 8 hours and can't approve, lower the damage or touch production.Your spec stays put
The CLI trims it on your machine and uploads only the skeleton of what the agent can touch.
npx @frailen/cli loginnpx @frailen/cli fuente recortar --agente soportenpx @frailen/cli fuente registrar --entorno staging --en-seconpx @frailen/cli bancoStart in staging.
Create your company's account and connect your API without touching production.