SaaS iMessage Agent Starter
A production-minded starter for giving a SaaS or online product a real agent experience through iMessage.
The deploy button intentionally launches a safe, zero-configuration message simulator first. Real iMessage delivery remains off until you connect a provider and implement the authorization-aware adapter for your product.
Why this exists
Most agent examples stop at chat UI, a webhook, or a model call. A trustworthy SaaS channel needs more:
- Durable multi-turn sessions that survive serverless and deployment interruption.
- Signed, bounded, deduplicated provider events.
- Secure account linking; a phone number is not authorization.
- Product-owned tools that reauthorize every read and write.
- Immediate low-risk writes with audit history, idempotency, and undo.
- Honest progress, typing, failure, and delivery behavior.
- Plain text and standalone URL bubbles that work in iMessage.
- Exact web handoffs with privacy-safe Open Graph previews.
- Feedback through the product's existing feedback system.
- Metadata-only PostHog MCP Analytics.
- Deployed-agent canaries and physical-device acceptance testing.
- Split-deployment origin safety and an operator-only real-provider canary.
This starter packages those boundaries without shipping a fake universal auth or database layer.
Architecture
Linq / iMessage
│ signed webhook
â–¼
Channel adapter ─── Next.js · Workflow · consent · delivery
│ authenticated turn
â–¼
Standalone Eve ──── durable context · tools · trace · evals
│ │
│ actor-scoped tools └── reply delivery
â–¼ â–¼
Your SaaS services Channel adapter → Linq
authorization · data · auditRead Architecture and Threat model before enabling a real channel.
The one-click button deploys only the safe simulator. A real channel uses three Vercel projects from this repository: the canonical SaaS app, the connector-owning channel adapter, and standalone Eve.
What ships
| Capability | Starter behavior |
|---|---|
| One-click Vercel deploy | Zero-secret response renderer and architecture demo |
| iMessage transport | Linq via Vercel Connect; disabled until explicitly configured |
| Agent runtime | Eve durable sessions and queue-per-conversation policy |
| Event durability | Vercel Workflow with encrypted event envelopes and retry hooks |
| SaaS tools | Typed read, reversible write, undo, handoff, and feedback examples |
| Native output | Markdown removal, safe splitting, standalone URL bubbles |
| Presence | Read and typing lifecycle tied to real execution |
| Analytics | Optional canonical $mcp_tool_call events via PostHog MCP Analytics |
| Rich handoff | Exact-link and dynamic OG example with privacy guidance |
| QA | Unit tests, Eve deployed evals, operator-only provider canary, CI, and physical-client checklist |
| Community | MIT license, contributing guide, code of conduct, security policy, templates, discussions |
Quick start
1. Deploy the safe simulator
Use the deploy button above. No credentials are requested and no message can be sent to a real person.
2. Run locally
Requirements: Node.js 24+ and pnpm.
git clone https://github.com/perryraskin/saas-imessage-agent-starter.git
cd saas-imessage-agent-starter
pnpm install
cp .env.example .env.local
pnpm devOpen http://localhost:3000.
3. Adapt it to your SaaS
Implement the five integration functions in src/lib/agent/saas-adapter.ts. The starter deliberately fails closed when SAAS_ADAPTER=custom is set but those methods still contain placeholders.
Follow Adapt your SaaS, including durable account bindings, event claiming, execution-time authorization, audit records, undo, feedback, and signed handoffs.
4. Connect iMessage
Follow Linq and Vercel Connect setup. Create the standalone Eve and channel-adapter projects, configure the three explicit directional origins, and attach Linq only to the channel adapter. Configure the webhook only after your adapter and account-linking flow pass their tests.
5. Prove the real path
pnpm check
CHANNEL_EVAL_TARGET_URL=https://your-deployment.vercel.app \
CHANNEL_EVAL_SECRET=your-isolated-eval-secret \
pnpm eval:deployedThen run the physical iPhone checklist.
The deployed Eve eval deliberately stops before Linq. Before production changes are called healthy, run the provider canary and require evidence through the actual connector-owning delivery deployment.
Principles
- The product database and domain services remain the source of truth.
- The provider handle and conversation history are never authorization.
- The model never gets direct database credentials.
- Low-risk writes may flow naturally only when they are idempotent, audited, and reversible.
- High-risk, destructive, financial, permission, signature, contract, and third-party actions stay unavailable by default.
- Never claim progress or completion from model text alone.
- URLs are raw, standalone messages; sensitive data never belongs in public OG metadata.
- Test the deployed agent and provider path, not just a mocked model call.
Build boundaries
pnpm build # Next.js simulator / canonical SaaS / channel adapter
pnpm build:agent # Standalone Eve service
pnpm check # Types, tests, and both production buildsBoth builds run from the repository root. Do not set the Eve project's Vercel
Root Directory to agent/; that separates Eve's generated output from the
shared dependency graph. The Eve build skips optional sandbox prewarming so the
starter remains buildable without a local sandbox runtime. If you add tools that
require a sandbox, explicitly configure and test a supported provider before
enabling them in production.
Project status
The repo is intentionally useful on day one and explicit about what remains adopter-specific. See Roadmap and Changelog. Eve is currently beta, so pin versions and review upstream release notes before upgrades.
Upstream foundations
- Vercel Eve
- Vercel Eve examples
- Vercel Personal Agent Template
- Vercel Connect + Linq
- Linq API documentation
- PostHog MCP Analytics
Contributing and security
Contributions are welcome. Read CONTRIBUTING.md, CODE_OF_CONDUCT.md, and SECURITY.md. Do not report vulnerabilities in public issues.
License
MIT © Perry Raskin.