Skip to content

connect banks through plaid, behind the plaid experiment - #111

Merged
hkonsti merged 6 commits into
mainfrom
hkonsti/plaid-integration-for-pap
Oct 16, 2026
Merged

hkonsti merged 6 commits into
mainfrom
hkonsti/plaid-integration-for-pap

Conversation

@hkonsti

@hkonsti hkonsti commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

What

Agents can read bank accounts through Plaid: balances and transactions, read-only, US and Canada. Banks sit behind the new plaid experiment, so only organizations with it turned on in the internal admin can connect one.

Connecting

  • Plaid Link runs in the browser (react-plaid-link) at /connections/new/plaid and /welcome/connections/plaid. An OAuth bank signs in through a popup, so there's no redirect URI.
  • POST /api/connections/plaid/link-token makes the Link token, asking for two years of Transactions. POST /api/connections/plaid with {publicToken} exchanges what Link returns for an access token.
  • Each bank login becomes its own connection, named after its bank and stored with Plaid's item id. A new bank connection gives agents nothing until its permissions are ticked.
  • Sign in to the bank again on the connection page uses Link's update mode on the same login, so the access token is kept. Plaid errors such as ITEM_LOGIN_REQUIRED tell the agent to ask the person to do this.
  • Disconnecting, and deleting an account, call /item/remove at Plaid (beforeDisconnect), which ends Plaid's monthly fee for the login.

Reading (records/plaid-connector.ts, live from Plaid on every request)

  • accounts (Read balances): each account's balances, from /accounts/get. These are as of Plaid's last update, so there's no per-request Balance fee.
  • transactions (Read transactions) is a nested collection: the accounts at the top, each holding its transactions newest first, 50 per page.
  • A search is one day (that day and earlier) or two days (the range between them), across every account.
  • Amounts read as a bank statement does, with money out negative.
  • On the agent side, a collection marked listsAll (new in @proxy/integrations) shows every field of a record in its row.

Experiment

  • EXPERIMENTS.plaid.
  • The link-token and connect routes answer 403 without it, before anything reaches Plaid.
  • The catalog (app and welcome flow) hides Plaid without it.
  • Existing bank connections keep working if the experiment is turned off later.
  • The docs page shows self-hosters a one-line SQL command that turns it on.

Self-hosting

  • PLAID_CLIENT_ID, PLAID_SECRET and PLAID_ENV (sandbox or production) are in the env schema, .env.example, docker-compose.yml and render.yaml.
  • Without the keys, Plaid is greyed out in the catalog with a link to the new docs page, connections/plaid.

Privacy policy

  • The data enumeration now names every kind of data a connected service may hold, so new integrations don't need an edit.
  • A new section, "Services connected through a third party", uses Plaid as its example.
  • New clauses cover billing information, sign-in confirmation (passkeys, authenticator apps, phone numbers), members of shared organizations and marketing email with an unsubscribe link.
  • Google Limited Use and training language are unchanged.

Why

Agents reading bank statements was the ask. Plaid's Transactions product covers it at $0.30 per connected login per month on Pay As You Go, and the Trial covers 10 logins for new US and Canada teams. The experiment lets us run it with a few organizations while Plaid's production review and its attestations are pending.

Tested

  • Connector tests: accounts, transactions, paging, searches by day, record ids, Plaid errors, writes refused.
  • Route tests: Link token (new and update mode), public token exchange, refusal without the experiment, missing keys.
  • Disconnect test: /item/remove is called.
  • Catalog tests: Plaid greyed out without keys, hidden without the experiment.
  • End to end in Sandbox (user_good / pass_good):
    • connected a bank through Link;
    • an agent read balances and transactions;
    • Sign in to the bank again opened Link in update mode;
    • disconnecting and deleting the account each removed the item at Plaid.
  • In the dev app with a fresh account: Plaid hidden and the link token answering 403 without the experiment; listed, with the link token issued, once it's turned on.
  • bun run typecheck, bun run test, bun run lint, docs and website builds.

Open workspace in Conductor

A bank is connected with Plaid Link in the browser and kept as a connection named by its bank.
Agents read its accounts' balances and each account's transactions, live from Plaid, with Read
balances and Read transactions each allowed on its own. Signing in to a bank again is Link's
update mode, and disconnecting removes the login at Plaid. Plaid is set up with PLAID_CLIENT_ID,
PLAID_SECRET and PLAID_ENV, and greyed out in the catalog without them.
…e privacy policy general

A collection marked listsAll shows every field a record has in its row on the agent side, so
an agent reads a transaction's date, amount, account, category and status without opening it.
Plaid's balances and transactions are marked so.

The privacy policy describes connected services and their data by kind rather than naming each
integration, and services connected through a third party, such as Plaid, in one section, so a
new integration doesn't need it changed.
- keep the plaid experiment on the shared catalog (isOffered), so the MCP
  instructions leave Plaid out for organizations without it
- sign in to a bank already connected again without the experiment
- remove the login at Plaid when the connection can't be saved
- refuse impossible days in searches and ids instead of throwing
- write amounts with their currency's digits, and every digit for one
  without an ISO code
- load Plaid's script only once Link is opened
- reuse Row for agent-side lists of every field, keeping Open in links
- share the page token helper between the Plaid and Calendar connectors
@hkonsti
hkonsti force-pushed the hkonsti/plaid-integration-for-pap branch from 139da28 to 580a317 Compare October 16, 2026 20:35
@hkonsti
hkonsti merged commit cc94117 into main Oct 16, 2026
2 checks passed
@hkonsti
hkonsti deleted the hkonsti/plaid-integration-for-pap branch October 16, 2026 20:43
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