iMessage Agent as a Service
- Linq
- Stripe Link
- Vercel
OpenInstinct, a multi-tenant iMessage agent service built with eve and Linq, with user accounts, scoped memory, an encrypted vault, cloud browser automation, and Stripe Link wallet integration.
- Linq
- Stripe Link
- Vercel
agent/agent.tstypescriptimport { defineAgent, defineDynamic } from "eve";
import { scheduledRunIdentity } from "@agent/lib/schedules/identity";
import { isScheduledAgentRunLeaseActive } from "@db/services/scheduled-agent-run-leases";
import { getGatewayModel } from "@db/services/settings";
import { scopeFromPrincipal } from "@agent/lib/principal-scope";
export default defineAgent({
defaultTools: false,
model: defineDynamic({
events: {
"step.started": async (_event, ctx) => {
const scheduledRun = scheduledRunIdentity(ctx.session.auth);
if (
scheduledRun &&
!(await isScheduledAgentRunLeaseActive(
scheduledRun.runId,
scheduledRun.leaseToken
))
) {
throw new Error("The scheduled run lease is no longer active.");
}
const caller = ctx.session.auth.current ?? ctx.session.auth.initiator;
if (!caller) throw new Error("An authenticated user is required.");
return getGatewayModel(scopeFromPrincipal(caller));
},
},
}),
reasoning: "low",
compaction: {
thresholdPercent: 0.7,
},
});
A personal iMessage assistant that can use a browser like you.
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. Deploy to your own Vercel account and get rolling.
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. 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.
Choose the free plans for Kernel and Neon during deployment. Kernel includes free usage credits, and AI Gateway includes credits for eligible models. Linq's managed connector and private Blob storage 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
- Click Deploy with Vercel above and select a Pro team. The guided flow connects Kernel for cloud browsers, Neon for Postgres, private Vercel Blob storage, a managed Linq line for iMessage, and Vercel AI Gateway for models.
- Complete the Linq phone verification, then open your deployed app and sign in with your phone number.
- Optionally set up a Link wallet for purchases or Google Workspace for Gmail, Calendar, and Contacts.
On first use, OpenInstinct creates independent Better Auth and vault-encryption 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.
Database, storage, and installation secrets
For a non-Vercel host or an installation that manages its own keys, set both secret overrides and the public application URL explicitly:
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
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 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.
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
pnpm exec eve link --project <your-vercel-project> --non-interactive, then
create and connect the store:
Outside Vercel, set BLOB_READ_WRITE_TOKEN from a private Blob store. Memory and
browser image capture use the same store.
Linq iMessage setup
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.
Attach Linq to an existing Vercel project
Link the checkout, create a line, and attach its connector for both outbound tokens and inbound webhooks:
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.
Google Workspace connection
OpenInstinct can use a user's Gmail, Calendar, and read-only Contacts through a
user-scoped Google OAuth grant. Vercel Connect stores and refreshes the tokens;
OpenInstinct stores only the stable user identity used to request them. Gmail
access deliberately uses gmail.modify, not the permanent-delete
mail.google.com scope.
-
In one Google Cloud project, configure the OAuth consent screen and enable the Gmail API, Google Calendar API, and People API.
-
Create OAuth web credentials. Add
https://connect.vercel.com/callbackas an authorized redirect URI, then download the client-secret JSON. -
Vercel expects top-level
clientIdandclientSecretkeys, not Google's nestedweb.client_idandweb.client_secretdownload. Convert the download into a temporary file outside the repository, then create and attach the connector:Never commit either credential file.
-
Set
GOOGLE_CONNECTOR_UIDto the returned UID and redeploy. The default isgoogle/open-instinct.
Gotchas:
- Attach the connector separately to every Vercel environment that should use it. A production attachment does not make preview or local development work.
- The Gmail read/modify scope is restricted. A Google OAuth app in Testing mode only works for listed test users, and those grants expire after seven days. Broader distribution requires Google's OAuth verification and may require a security assessment.
- The scopes requested here must also be declared on the Google consent screen. After changing scopes or enabled APIs, disconnect and reconnect the account so Google issues a grant with the new access.
- The grant is keyed to the authenticated OpenInstinct user. iMessage reaches the same grant only when its verified phone number maps to that Better Auth account.
- Google Contacts search uses a provider-side lazy cache, so a contact created moments ago may not appear immediately.
- User-requested email and calendar operations run without an extra Eve tool approval. Calendar events with attendees send Google invitations.
Link 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
-
Create or sign in to a Stripe account. Follow Stripe's Link OAuth registration guide and submit the linked Link Agent Wallet application form. Stripe issues your OAuth
client_idandclient_secretafter registration. -
In that application, register your exact callback URL:
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. -
Add these values in Vercel → Project → Settings → Environment Variables for each environment that will use Link, or in
.env.localwhen developing:Use the Stripe publishable key (
pk_…), not a Stripe secret API key (sk_…).BETTER_AUTH_URLis 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. -
Push a commit to the connected Git repository to redeploy, or restart your local server. Vercel builds and
pnpm devapply the database migrations automatically; with an externally managed local database, runpnpm db:migratebefore 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.
Wallet authorization and access limits
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 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.
Eve version and active-session compatibility
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.
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.
Local development
Local development requires:
- Node.js 24 and pnpm 11.24.0
- Docker Desktop or another running Docker Compose installation
- Kernel credentials from a Kernel API key or a linked Vercel Marketplace resource
- AI Gateway access from an API key or a linked Vercel project's OIDC token
First clone and install the application:
For fully manual setup, copy the environment template and add your Kernel and AI Gateway keys:
If you already use a Vercel project, link it to pull AI Gateway access. If that project does not have Kernel yet, the Marketplace CLI provisions the free Developer plan, connects it to the project, and pulls its environment variables:
Then start OpenInstinct:
pnpm dev starts PostgreSQL from compose.yaml, applies the committed database
migrations, and starts the application. Stopping the development process also
stops and removes the PostgreSQL container; its data remains in the
postgres-data volume for the next run. Run pnpm dev:app when intentionally
using an externally managed database instead. If KERNEL_API_KEY is missing,
pnpm dev stops before starting Docker and points back to the recommended
Vercel flow or the manual .env.local setup.
Local development otherwise uses the same vault, Kernel browser, and AI Gateway path as the Vercel deployment. Better Auth and vault encryption use stable local-only defaults when their variables are unset. Vercel deployments provision them automatically in private Blob; other production hosts require explicit secrets.
[!WARNING] This is not software intended for production use.