Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
283 changes: 168 additions & 115 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,131 +4,148 @@

**A personal iMessage assistant that can use a browser like you.**

It can do your chores, book you movie tickets, or handle your groceries.
You stay in control of your passwords, credit cards and context.
It can do your chores, book movie tickets, or handle your groceries.
You stay in control of your passwords, credit cards, and context.

It's Open Source, self-hostable, and can use any model.
One-click deploy to Vercel and get rolling.
It's open source, self-hostable, and can use any model.
Deploy to your own Vercel account and get rolling.

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FMerit-Systems%2FOpenInstinct&project-name=open-instinct&repository-name=open-instinct&connect=%5B%7B%22type%22%3A%22linq%22%2C%22env%22%3A%22LINQ_CONNECTOR%22%2C%22triggers%22%3Atrue%2C%22triggerPath%22%3A%22%2Feve%2Fv1%2Flinq%22%7D%5D&stores=%5B%7B%22type%22%3A%22integration%22%2C%22protocol%22%3A%22other%22%2C%22productSlug%22%3A%22kernel%22%2C%22integrationSlug%22%3A%22kernel%22%7D%2C%7B%22type%22%3A%22integration%22%2C%22protocol%22%3A%22storage%22%2C%22productSlug%22%3A%22neon%22%2C%22integrationSlug%22%3A%22neon%22%7D%2C%7B%22type%22%3A%22blob%22%2C%22access%22%3A%22private%22%7D%5D)

<img src=".github/demo.png" alt="OpenInstinct booking movie tickets over iMessage — it walks Fandango to checkout and reports the theater, showtime, seat, and total" width="640">

</div>

> **Agents:** For the simplest deployment, give your human the
> **Deploy with Vercel** link above and have them complete the guided flow. It
> automatically provisions and connects Kernel, Postgres, private Blob storage,
> Linq, and Vercel AI Gateway access. OpenInstinct creates its installation
> secrets on first use.
> **Agents:** Give your human the **Deploy with Vercel** link above. The guided
> flow provisions the required services and credentials. Google Workspace and
> Link wallet connections have separate setup steps below.

## Why self-host?

Personal agents are much more useful when they can sign in, book, buy and act
on your behalf. But your accounts, your passwords, are the keys to your digital
kingdom. OpenInstinct runs in your own Vercel account. Secrets are encrypted
before they touch your database and models never see them. Verify yourself by
reading the code!
Personal agents are much more useful when they can sign in, book, buy, and act
on your behalf. OpenInstinct runs in your own Vercel account. Saved vault secrets
are encrypted before they reach your database, and browser autofill keeps saved
passwords out of the model's context. You can read the code to see how it works.

## Requirements and costs

You can use free tiers for the supporting services. **Vercel requires the Pro
plan.** OpenInstinct checks for scheduled work every minute; Vercel's Hobby plan
only allows cron jobs that run once per day, so it cannot deploy this schedule.
See [Vercel's cron limits](https://vercel.com/docs/cron-jobs/usage-and-pricing).

Choose the free plans for Kernel and Neon during deployment.
[Kernel](https://kernel.sh/pricing) includes free usage credits, and
[AI Gateway](https://vercel.com/docs/ai-gateway/pricing) includes credits for
eligible models. [Linq's managed connector](https://vercel.com/docs/connect/pricing)
and [private Blob storage](https://vercel.com/docs/vercel-blob/usage-and-pricing)
are billed through Vercel; Blob usage draws from your Pro usage credit.
Free plans and credits have limits, and usage can incur additional charges.
Purchases approved through Link are paid from your wallet.

## Deployment

The deploy button provisions [Kernel](https://kernel.sh) for cloud browsers,
[Neon](https://neon.tech) for Postgres, and a private Vercel Blob store for
browser images, per-user memory, and installation secrets. It also creates and
attaches a [Linq](https://linq.app) connector for iMessage. Vercel AI Gateway
handles inference. Usage is billed to your Vercel account.
1. Click **Deploy with Vercel** above and select a **Pro** team. The guided flow
connects [Kernel](https://kernel.sh) for cloud browsers,
[Neon](https://neon.tech) for Postgres, private Vercel Blob storage, a managed
[Linq](https://linq.app) line for iMessage, and Vercel AI Gateway for models.
2. Complete the [Linq phone verification](#linq-imessage-setup), then open your
deployed app and sign in with your phone number.
3. Optionally set up a [Link wallet](#link-wallet) for purchases or
[Google Workspace](#google-workspace-connection) for Gmail, Calendar, and
Contacts.

On first use, OpenInstinct creates independent Better Auth and vault-encryption
keys in the private Blob store. Vercel supplies the application URL, database,
Kernel, Blob, and Linq configuration, so the deploy flow requires no
environment-variable values. For a non-Vercel host or an existing installation
that manages its own keys, set both secret overrides and the public application
URL explicitly:
keys in the private Blob store. The deploy flow supplies the application URL
and required service configuration automatically; you do not need to copy
environment-variable values for the base installation.

<details>
<summary>Database, storage, and installation secrets</summary>

For a non-Vercel host or an installation that manages its own keys, set both
secret overrides and the public application URL explicitly:

```bash
BETTER_AUTH_SECRET="$(openssl rand -base64 32)"
BETTER_AUTH_URL=https://your-host
SECRET_ENCRYPTION_KEY="$(openssl rand -base64 32)"
```

The application database schema and versioned migrations live in `db/`. The
Drizzle application store uses `DATABASE_URL` for runtime queries; its migration
commands require the direct `DATABASE_URL_UNPOOLED` connection. Run
`pnpm db:migrate` before starting against a new or upgraded local database.
Vercel uses Turbo to run the uncached migration task before its application
build. See [`db/README.md`](db/README.md) for existing-database adoption,
environment loading, and constraint-validation sequencing. Better Auth retains
its separate migration path.
Application migrations live in `db/`. Runtime queries use `DATABASE_URL`;
migrations require the direct `DATABASE_URL_UNPOOLED` connection. Run
`pnpm db:migrate` before using a new or upgraded database. `pnpm dev` and Vercel
builds run these migrations automatically. See [`db/README.md`](db/README.md)
for existing-database adoption and Better Auth's separate migration path.

Treat the private Blob store as production key material: deleting it loses the
automatically generated encryption key, and rotating that key requires
re-encrypting existing vault values.

### Blob storage

The one-click deploy creates and connects a private Blob store automatically.
Vercel supplies `BLOB_STORE_ID` and a short-lived `VERCEL_OIDC_TOKEN` to each
deployment, so there is no long-lived Blob credential to copy.
The deploy button connects a private Blob store. Vercel supplies `BLOB_STORE_ID`
and a short-lived `VERCEL_OIDC_TOKEN`, so there is no Blob credential to copy.

OpenInstinct uses this store for persistent per-user memory and browser images.
Production conversations require it because memory is recalled before each agent
turn. Local Eve development uses process-local memory instead.

Ongoing undertakings use a separate `workstreams` memory slot backed by the
application database. Run the application migrations before using this feature;
it needs no additional service or credentials. The root agent can save goals,
constraints, decisions, source-linked observations, and unresolved steps across
conversations. It recalls an index of the eight most recently updated active or
waiting workstreams, then reads the selected record before continuing. Older and
completed workstreams remain searchable.

Workstreams are scoped by authenticated workspace and Eve's deployment-aware
memory key. Updates require the current revision. Each scope retains content for up to 100
bounded records; the agent asks which obsolete record to forget at capacity.
Forgetting erases the content and source references, retaining only a tombstone
to prevent an interrupted save from restoring them. Existing chat history is
unchanged. This slot is available only in interactive root turns; remembering
work does not start a job, create a schedule, or authorize an action.
The database also stores `workstreams`: goals, decisions, observations, and
unfinished steps the agent can recall across conversations. They are scoped to
the authenticated workspace and Eve's deployment-aware memory key. Each scope
holds up to 100 records, with the eight most recently updated active or waiting
records recalled first; older records remain searchable. Updates require the
current revision. At capacity, the agent asks which obsolete record to forget.
Forgetting removes the content and source references while retaining a tombstone
against interrupted saves; chat history is unchanged. Saving a workstream does
not start a job, create a schedule, or authorize an action. This memory slot is
available only in interactive root turns.

For an existing Vercel project, link it first with
`eve link --project <your-vercel-project> --non-interactive`, then create and
connect the store with one command:
`pnpm exec eve link --project <your-vercel-project> --non-interactive`, then
create and connect the store:

```bash
pnpm exec vercel blob create-store open-instinct-images --access private --yes --environment production --environment preview --environment development
```

Outside Vercel, set `BLOB_READ_WRITE_TOKEN` from a private Blob store instead.
The memory provider uses that token explicitly, and browser image capture uses the
same store.
Outside Vercel, set `BLOB_READ_WRITE_TOKEN` from a private Blob store. Memory and
browser image capture use the same store.

</details>

### Linq iMessage setup

The deploy button creates a managed line, writes `LINQ_CONNECTOR`, and
attaches the inbound webhook trigger automatically. For an existing Vercel
project, link the checkout, create a Linq line, and attach its connector for both
app tokens and inbound webhook triggers:
The deploy button creates a managed line, sets `LINQ_CONNECTOR`, and attaches
the inbound webhook automatically.

Before your first sign-in, open the connector's **Vercel Connect** settings and
follow its one-time **Phone Numbers** verification instruction. Additional users
verify themselves by messaging the connector's Linq number once.
`LINQ_PHONE_NUMBER` is an optional E.164 override that adds a click-to-message
shortcut in the workspace; delivery uses the line assigned to the connector.

<details>
<summary>Attach Linq to an existing Vercel project</summary>

Link the checkout, create a line, and attach its connector for both outbound
tokens and inbound webhooks:

```bash
vercel link
vercel connect create linq --connection-method line --name open-instinct --json
vercel connect attach <returned-connector-uid> --project <your-vercel-project> --environment production --triggers --trigger-path /eve/v1/linq --yes
vercel env add LINQ_CONNECTOR production --value <returned-connector-uid> --yes
eve deploy --non-interactive --yes
pnpm exec eve link --project <your-vercel-project> --non-interactive
pnpm exec vercel connect create linq --connection-method line --name open-instinct --json
pnpm exec vercel connect attach <returned-connector-uid> --project <your-vercel-project> --environment production --triggers --trigger-path /eve/v1/linq --yes
pnpm exec vercel env add LINQ_CONNECTOR production --value <returned-connector-uid> --yes
```

The create command returns the connector UID. Repeat the attachment and
environment-variable steps for preview or development if those environments
should use Linq too. `LINQ_PHONE_NUMBER` is an optional E.164 override that adds
a click-to-message shortcut in the workspace; Linq delivery itself uses the
line assigned to the connector.
The create command returns the connector UID. Push a commit to the project's
connected Git repository to deploy the configuration. Repeat the attachment and
environment-variable steps for preview or development as needed. Keep
`--triggers --trigger-path /eve/v1/linq`: without them, the app can send messages
but cannot receive them.

Before the first sign-in, open the connector's Vercel Connect settings and
follow the one-time **Phone Numbers** verification instruction. Additional users
verify themselves by messaging the connector's Linq number once. The
`--triggers --trigger-path /eve/v1/linq` options are also required: attaching a
connector without them permits outbound token access but does not forward
incoming messages to OpenInstinct.
</details>

## Google Workspace connection

Expand Down Expand Up @@ -184,57 +201,93 @@ Gotchas:

## Link wallet

The root agent mounts `@stripe/link-integrations-eve` in
`agent/extensions/link.ts`. It uses Stripe's bundled wallet tools and skills,
with per-user authorization through the existing Better Auth
account. It does not use a shared wallet token.

To enable it, register a Link OAuth client and configure `LINK_CLIENT_ID`,
`LINK_CLIENT_SECRET`, and `STRIPE_PUBLISHABLE_KEY` on the server. Register the
exact redirect URI `https://<your-app-host>/api/auth/callback/link` with Stripe,
including a separate localhost URI when developing locally. Set
`BETTER_AUTH_URL` to the canonical application origin. These values are optional
for installations that do not use Link.

Apply the database migration with `pnpm db:migrate` before enabling Link. It
enforces one Link wallet per OpenInstinct account. Disconnect the current wallet
before connecting a different one; reconnecting the same wallet refreshes its
grant.

Users connect or disconnect their wallet from **Link wallet** in the sidebar.
An agent request that needs a wallet sends a native connection link. Opening it
redirects to Link's consent screen after any required OpenInstinct sign-in, then
resumes through Eve's authorization callback. Purchase approval links use Link's
original URLs directly. Connection attempts expire after ten
minutes and belong to the signed-in user. Better Auth stores encrypted grants
and refreshes tokens; disconnection revokes the Link grant before removing it.
Phone sign-in continues to work after disconnecting a wallet.
Link lets users approve purchases from their own wallet. It is optional and
requires separate setup after deployment; the deploy button does not configure
it. Stripe currently supports Link Agent Wallet for US and Canadian consumers.

### Enable Link on your deployment

1. Create or sign in to a [Stripe account](https://dashboard.stripe.com/register).
Follow [Stripe's Link OAuth registration guide](https://docs.stripe.com/agentic-commerce/agents/link-agent-wallet/oauth)
and submit the linked **Link Agent Wallet application form**. Stripe issues
your OAuth `client_id` and `client_secret` after registration.
2. In that application, register your exact callback URL:

```text
https://<your-app-host>/api/auth/callback/link
```

For local development, also register
`http://localhost:3000/api/auth/callback/link` (or your actual local origin).
The app's **Link wallet** page displays the callback URL for your installation.

3. Add these values in **Vercel → Project → Settings → Environment Variables**
for each environment that will use Link, or in `.env.local` when developing:

| Variable | Value |
| ------------------------ | --------------------------------------------------------------------------------- |
| `LINK_CLIENT_ID` | OAuth `client_id` issued by Stripe |
| `LINK_CLIENT_SECRET` | OAuth `client_secret` issued by Stripe |
| `STRIPE_PUBLISHABLE_KEY` | Publishable key from your [Stripe API keys](https://dashboard.stripe.com/apikeys) |
| `BETTER_AUTH_URL` | Canonical app origin, such as `https://your-app.vercel.app` |

Use the Stripe publishable key (`pk_…`), not a Stripe secret API key (`sk_…`).
`BETTER_AUTH_URL` is the origin only; the registered callback adds
`/api/auth/callback/link`. Keep the OAuth client secret in server settings;
do not commit it or paste it into chat.

4. Push a commit to the connected Git repository to redeploy, or restart your
local server. Vercel builds and `pnpm dev` apply the database migrations
automatically; with an externally managed local database, run
`pnpm db:migrate` before starting the app.

### Connect your wallet

Sign in to OpenInstinct with your phone number, open **Link wallet** in the
sidebar, and choose **Connect Link**. Approve the connection on Link's consent
screen. When you return, the page should say **Your Link wallet is connected**.
If it still says Link is unavailable, check that all three Stripe variables are
set on the deployed environment and that you redeployed after adding them.

Connecting a wallet does not approve a purchase. Each spend request requires
your approval in Link. You can connect one wallet per OpenInstinct account;
disconnect it before switching wallets. Disconnecting revokes wallet access and
leaves phone sign-in available.

<details>
<summary>Wallet authorization and access limits</summary>

The agent uses `@stripe/link-integrations-eve` with per-user Better Auth grants.
Better Auth encrypts stored grants and refreshes tokens. Agent-initiated
connection links belong to the signed-in user and expire after ten minutes;
purchase approvals use Link's original URLs.

Wallet access is available in interactive conversations, not scheduled workers
or scheduled result delivery. Spend requests run without an extra Eve tool
approval and always request purchase approval in Link. Its tools can
return payment credentials into stored Eve tool results; the bundled skills
instruct the agent not to repeat them in chat. Financial-data tools also require
the corresponding Link grant scopes; the default grant requests
`payment_methods.agentic` and `userinfo:read`.
or scheduled result delivery. Spend requests do not have an additional Eve
approval step. Payment credentials can appear in stored Eve tool results; the
bundled skills instruct the agent not to repeat them in chat. The default grant
requests `payment_methods.agentic` and `userinfo:read`. Balances and transactions
require additional financial-data scopes and connected-source permissions.

</details>

## Eve compatibility
<details>
<summary>Eve version and active-session compatibility</summary>

This branch pins Eve `0.66.3` and the published Link extension `0.2.4`.
This repository pins Eve `0.66.3` and the published Link extension `0.2.4`.
The extension's tool contract is supported directly, so it needs no compatibility
rebuild. Browser work uses the background workflow and `agentId` continuation
APIs supported by this Eve version.

Do not move an active session from Eve `0.69` onto this deployment. Keep existing
sessions on their owning deployment until they finish, and start a new
conversation on this branch's deployment. This rollback does not reset or
cancel production sessions.
Keep active sessions on their owning deployment until they finish; do not move
an Eve `0.69` session onto this `0.66.3` deployment. Start a new conversation
after changing Eve versions.

</details>

## Local development

The **Deploy with Vercel** flow above is the simplest way to run OpenInstinct. It
provisions the required services and credentials automatically. Local
development is a manual path and requires:
Local development requires:

- Node.js 24 and pnpm 11.24.0
- Docker Desktop or another running Docker Compose installation
Expand Down
Loading