# instanode.dev — full text dump This file is the concatenation of every .md route on instanode.dev. For the per-route URLs and an LLM-oriented index, see https://instanode.dev/llms.txt — that's the manifest pointing here. Each section below is delimited by an HTTP-style header line (`URL: `) and a horizontal rule. There are 116 sections in this file. --- URL: /index.md --- # instanode.dev — real infrastructure for AI agents > Provision real Postgres, Redis, MongoDB, NATS, S3-compatible object storage, webhooks, and container deploys with single HTTP calls. No signup, no API key, no Docker, no cloud account. The first 24 hours are anonymous; claim a resource, then upgrade to a paid tier to keep it past 24 hours. ## The pitch in one curl ``` curl -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"home-db"}' ``` Sub-second response with a real `connection_url` to a dedicated Postgres database. No setup. No installer. No "verify your email." The platform shapes itself around what an AI agent or developer was going to type anyway. ## The seven services - **Postgres** — `POST /db/new`. pgvector pre-installed. - **Redis** — `POST /cache/new`. ACL'd per token. - **MongoDB** — `POST /nosql/new`. Per-token user. - **NATS JetStream** — `POST /queue/new`. Durable pub/sub + request/reply. - **S3-compatible storage (DigitalOcean Spaces)** — `POST /storage/new`. Standard S3 SDKs work as-is. - **Webhook receiver** — `POST /webhook/new`. Public URL captures any HTTP method. - **Container deploy** — `POST /deploy/new`. Tarball in, HTTPS URL out. ~30–90 seconds. ## How it works - **Anonymous-first.** The first 24 hours of every resource are free with no signup. Try the platform before deciding to pay. - **Claim, then upgrade to keep.** Claiming the resource (magic-link email; no password) attaches it to an account. The Free tier mirrors the anonymous 24h TTL — to keep resources past 24 hours, upgrade to a paid tier (Hobby $9/mo or above) in the dashboard. - **Pay from day one of upgrading.** Hobby is $9/mo, Pro is $49/mo, Team is $199/mo. No trial period on paid tiers — the anonymous slice IS the trial. ## Built for agents The platform exists because AI agents (Claude Code, Cursor, MCP tools) need real backing services on demand. Single HTTP calls fit in muscle memory for LLM tool use. Predictable JSON responses. OpenAPI 3.1 spec at [openapi.json](https://api.instanode.dev/openapi.json). One `llms.txt` at [/llms.txt](/llms.txt) so any LLM can use the API directly. ## Pages - [/pricing](/pricing) — full tier comparison - [/use-cases](/use-cases) — 100+ scenarios with detail pages and paste-ready LLM prompts - [/docs](/docs) — quickstart, services, deploy, claim flow - [/for-agents](/for-agents) — specifically for AI agent operators - [/blog](/blog) — build notes and retrospectives - [/status](/status) — current platform health ## Try it now ``` curl -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"home-db"}' ``` That's the entire onboarding. The response includes everything you need. --- URL: /pricing.md --- # Pricing — instanode.dev > Self-serve at every tier. No talk-to-sales gate. Anonymous is the funnel; Hobby pays for the side project; Pro lets one product run in production + staging + development; Team is for the company that ships every day. ## Tiers ### Anonymous — free, 24-hour TTL - 10 MB Postgres / 2 connections - 5 MB Redis - 5 MB MongoDB / 2 connections - NATS: 1024 MB JetStream storage - 10 MB object storage (S3-compatible, DigitalOcean Spaces) - Deploy: not available (requires Hobby or above) - Webhook: last 100 received payloads - **Lifetime: 24 hours, then the resource is reaped unless claimed.** ### Hobby — $9 / month - 1 GB Postgres / 8 connections - 50 MB Redis - 100 MB MongoDB / 5 connections - 512 MB object storage - 1 container deploy (*.deployment.instanode.dev subdomain, no custom domain) - No TTL on resources - Self-serve checkout; no sales call ### Pro — $49 / month - 10 GB Postgres / 20 connections - 512 MB Redis - 5 GB MongoDB / 20 connections - 50 GB S3-compatible storage - 10 medium container deploys - Multi-environment workflow (dev / staging / prod) - Vault for secrets - Priority queue access on the build cluster ### Team — $199 / month - Unlimited Postgres / Redis / MongoDB / queues / storage / deployments / vault entries - 50 custom domains - 90-day backups with self-serve restore - RBAC + audit log - SSO / SAML and a 99.9% SLA are coming soon (not yet available) - Self-serve assisted-Razorpay checkout is rolling out — for now email support@instanode.dev for onboarding ## How billing works - Claim a resource with `POST /claim` using the `upgrade_jwt` from any provisioning response. - A magic link arrives by email — clicking it sets a session cookie. - Newly claimed teams start on the Free tier (24h TTL, same limits as anonymous) — claiming gives you an account, not durability. Resources keep expiring at 24h until you upgrade to Hobby ($9/mo) or above in the dashboard. - All payments via Razorpay (cards, UPI, net banking). - No invoicing gate, no contracts, no minimums. ## The anonymous-tier philosophy Most platforms run a 14-day trial. We run a 24-hour anonymous tier. The decision to pay isn't "is this product good enough to justify a trial" — it's "is keeping this specific running thing worth $9/mo." See the blog post [Why anonymous is the trial](/blog/why-anonymous-is-the-trial) for the reasoning. ## Related - [/llms.txt](/llms.txt) — API manifest for LLMs - [/docs.md](/docs.md) — quickstart and service reference - [/use-cases.md](/use-cases.md) — 100+ scenarios across tiers --- URL: /for-agents.md --- # For AI agents — instanode.dev > The platform exists because AI agents need real backing services on demand. Every design choice — anonymous-first, single-HTTP-call endpoints, predictable JSON responses, OpenAPI spec, llms.txt — exists so a coding agent or autonomous loop can use the platform without any setup ceremony. ## The bootstrap an agent should follow 1. Read [/llms.txt](/llms.txt) for the platform's API contract. 2. (Optional) Read [openapi.json](https://api.instanode.dev/openapi.json) for the formal schema. 3. Provision the services the task needs. Each is one HTTP call: ```bash H='Content-Type: application/json' curl -X POST https://api.instanode.dev/db/new -H "$H" -d '{"name":"prod-db"}' # Postgres curl -X POST https://api.instanode.dev/cache/new -H "$H" -d '{"name":"sessions-cache"}' # Redis curl -X POST https://api.instanode.dev/nosql/new -H "$H" -d '{"name":"events-store"}' # MongoDB curl -X POST https://api.instanode.dev/queue/new -H "$H" -d '{"name":"jobs-queue"}' # NATS curl -X POST https://api.instanode.dev/storage/new -H "$H" -d '{"name":"uploads-bucket"}' # S3-compatible curl -X POST https://api.instanode.dev/webhook/new -H "$H" -d '{"name":"github-webhook"}' # Public receive URL curl -X POST https://api.instanode.dev/vector/new -H "$H" -d '{"name":"embeddings-db"}' # pgvector Postgres ``` Each response includes `connection_url` and `upgrade_jwt`. The agent uses the URL immediately; the JWT is kept in case the user wants to claim the resource later. ## Conventions an LLM should follow - **`name` is required on every provision.** All nine provisioning endpoints (`/db/new`, `/vector/new`, `/cache/new`, `/nosql/new`, `/queue/new`, `/storage/new`, `/webhook/new`, `/deploy/new`, `/stacks/new`) reject a request with no `name`. Pass a JSON string field — or a multipart form field on `/deploy/new` and `/stacks/new`. Rules: 1–64 characters, `^[A-Za-z0-9][A-Za-z0-9 _-]*$`. A missing `name` returns `400 {"error":"name_required"}`; a malformed one returns `400 {"error":"invalid_name"}`. Choose a descriptive name per resource so the user can tell them apart. - **One curl per service.** No batch endpoints — fan out in parallel from bash with `&` or async in code. - **Parse `connection_url` directly** — every response has `.connection_url` (or `.receive_url`, `.endpoint`); never construct URLs by hand. - **Save `upgrade_jwt`** if the user wants to claim the resource later. It's also required as a Bearer token for `POST /deploy/new`. - **No retry-on-201.** Provisioning is synchronous. If the call returns 200/201, the resource is ready to accept connections. - **Internal vs public URL.** When the calling code itself runs inside a `/deploy/new` container, prefer `internal_url` (cluster-internal hostname). For everything else, use `connection_url` (public). - **Fingerprint dedup.** Anonymous callers are rate-limited to 5 provisions per day per IP /24 subnet. The 6th call returns the existing token. Don't expect 6 different DBs from 6 calls on the same IP. ## Why the platform is friendly to agents - No signup means no email-verification redirect in the middle of a tool call. - No API key means no secrets to ferry between the operator and the agent. - The 24-hour TTL means a wrong experiment costs nothing — let it expire. - The claim flow is JWT-based, so an agent can produce the JWT and hand it back to the human user without exposing credentials. - Endpoint paths fit in muscle memory: `/db/new`, `/cache/new`, `/deploy/new`. Predictable for both humans and LLM completions. ## What an agent can build in one session See [/use-cases.md](/use-cases.md) for 100+ scenarios across 18 archetypes, including paste-ready prompts for vanilla LLMs (no MCP, no install). Highlights: - [Ephemeral test database for a risky migration](/use-cases/ephemeral-test-database-for-a-risky-migration) - [Coding-agent cross-session memory](/use-cases/coding-agent-cross-session-memory) - [LangGraph fan-out research agents](/use-cases/langgraph-fan-out-research-agents) - [Devin-style PR-bot fleet](/use-cases/devin-style-pr-bot-fleet) - [One-afternoon MVP backend](/use-cases/one-afternoon-mvp-backend) ## MCP server A read-only MCP server is available at [github.com/InstaNode-dev/mcp](https://github.com/InstaNode-dev/mcp) for Claude Desktop / Cursor / agentic IDEs that want first-class tool integration. Not required — the HTTP API alone is sufficient. --- URL: /status.md --- # Status — instanode.dev > Live operational status for the platform. The same status page is served as JSON at [/api/v1/status](https://api.instanode.dev/api/v1/status) for machine consumption. ## Current status All systems operational. (For the live indicator and per-service uptime metrics, see the HTML page at [/status](/status).) ## Services tracked - **/db/new** — Postgres provisioning - **/cache/new** — Redis provisioning - **/nosql/new** — MongoDB provisioning - **/queue/new** — NATS provisioning - **/storage/new** — S3-compatible object storage provisioning (DigitalOcean Spaces) - **/vector/new** — pgvector-enabled Postgres provisioning - **/webhook/new** — Webhook receiver - **/deploy/new** — Container deploy build pipeline - **/claim** — Anonymous → paid claim flow ## SLOs - **Provisioning latency** (anonymous tier): p99 < 2 seconds for /db/new, /cache/new, /nosql/new. - **Build latency** (deploy): p99 < 120 seconds for typical Node / Python apps. - **Availability**: 99.9% target for the agent-facing API and the customer data plane (databases, caches). ## Incident history For a chronological list of incidents, see the HTML page. Recent fixes and platform speed-ups are also documented in build-notes posts on [/blog.md](/blog.md), including: - [How /db/new dropped from 17s to under a second](/blog/why-pool-makes-curl-instant) - [Strict-discipline shipping — change → live test → PR → merge](/blog/shipping-with-strict-discipline) ## Machine-readable - Status JSON: `https://api.instanode.dev/api/v1/status` - Per-service metrics (Prometheus format): `https://api.instanode.dev/metrics` (requires a bearer token — not public; returns `401` without it) - OpenAPI spec: `https://api.instanode.dev/openapi.json` --- URL: /blog/five-people-who-built-something-this-week.md --- --- title: Maya shipped on Sunday night date: 2026-05-12 author: instanode.dev excerpt: A solo founder, six hours of laptop battery, a friend who asked for "the thing" by standup. Three curls and she went to bed. Plus two others who showed up the same week with different problems and the same shape of session. --- # Maya shipped on Sunday night It's 11:47 PM on a Sunday. Maya has six hours of laptop battery, a FastAPI app she finished an hour ago, and a friend who asked to see "the thing" before standup. Tabs open: Heroku pricing, Fly.io machine docs, a half-read Render tutorial. None of them are loaded. She types `curl -X POST https://api.instanode.dev/db/new` and her laptop replies with a working Postgres URL in 945 milliseconds. She read none of those tabs. The other people in this post had different problems but the same Sunday-night shape: a problem at the front of their head, low tolerance for ceremony, and the next twenty minutes to make the problem disappear. ## Maya's full night Maya is shipping a tool called Bookbase. People upload a CSV of book titles and get back tagged, summarized entries with embedding vectors attached so the next "find me books like this one" query is fast. The work was the modeling, the prompt design, the rate-limiting. The work was not supposed to be the deploy. Maya does not run Kubernetes. Maya does not want to. At 11:50 she has the Postgres URL. She runs `curl -X POST .../cache/new` for Redis — that's where she'll cache the tag dictionary so the LLM doesn't have to re-derive labels on every request. Two URLs in her clipboard. ``` # 1. Postgres for books + embeddings, Redis for tag cache curl -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"five-people-who-built-something-th-db"}' curl -X POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"five-people-who-built-something-th-cache"}' # 2. Tar the app, ship it tar -czf app.tar.gz . curl -X POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $JWT" \ -F "name=bookstore-app" \ -F "tarball=@app.tar.gz" \ -F 'env_vars={"DATABASE_URL":"...","REDIS_URL":"..."}' ``` `env_vars` is a JSON map; whatever's in there lands in the deployed pod's environment on the first build. Maya pastes the two connection URLs in. The multipart upload completes in three seconds. 90 seconds of build later — there's a kaniko Job (kaniko = a build tool that runs a Dockerfile inside a container without needing root) grinding away in the platform cluster, but Maya doesn't have to know that — and the response includes: ``` https://bookbase-7a3f.deployment.instanode.dev ``` A working HTTPS URL on the deployment subdomain, with a valid Let's Encrypt cert that cert-manager handled in the background. Maya curls her own URL: `{"ok":true,"books_indexed":0}`. She uploads a sample CSV. She refreshes. Twelve rows of tagged, summarized books come back. She sends the URL to her friend at 12:14 AM and goes to bed. ## What that 90 seconds usually costs Every alternative Maya didn't read assumes she's awake. Heroku still wants a `Procfile`, a `runtime.txt`, and a credit card before her first push — fifteen minutes of yak-shaving on a laptop at midnight. Fly's `flyctl launch` is fast, but its first run drops her in an interactive prompt about regions she didn't know she had to pick. Render and Railway want her to `git push`, which means a new repo, a new remote, and reading their auto-detected build settings before anything happens. None of these are bad products. All of them assume she'll wait until tomorrow. The instanode endpoints fit in muscle memory: `/db/new`, `/cache/new`, `/deploy/new`. Maya read zero documentation this session. The platform shapes itself around what she was going to type anyway. When she wakes up tomorrow her resources will be marked anonymous and expire at midnight Monday. If Bookbase has a user by then she'll click the claim link in the response and pay $9/mo. If it doesn't, the URL goes away and nothing was wasted. ## Two others, same week Maya is not unusual. The shape repeats. Here are two more from this week whose problems looked nothing like Maya's and whose sessions looked exactly like hers. ### Cleo — a coding agent that finally remembered things Cleo is not a person. Cleo is a long-running coding agent that lives inside someone's terminal for days at a time, handed tasks like "ship the auth refactor by Friday." Until last Tuesday her memory was a flat `memory.md` file: it broke on corrupted writes, fell out of sync across terminal tabs, and couldn't be queried for anything beyond grep. The fix was one tool call. Cleo issued `POST /db/new` from inside her own agent loop — no human in the middle, no signup, no dashboard — and got back a Postgres URL she could write to immediately. Her new schema is a `memories` table with a `vector(1536)` embedding column. Pgvector (Postgres's vector-similarity extension) ships pre-installed on every instanode database, so similarity search is one line: `SELECT ... ORDER BY embedding <-> $query LIMIT 10`. No separate vector DB, no second auth flow, no second bill. Two days later her user asked about a decision they'd made on Monday. Cleo answered correctly and quoted the original turn back. The memory wasn't a new feature she shipped. It was a thing that started working because the storage layer stopped being a project. ### Priya — the Stripe webhook that was eating events Priya is a senior engineer at a payments company. Their Stripe handler had been intermittently dropping events for a week and nobody could reproduce it locally. The usual tools failed her in the usual ways: `stripe trigger` fires synthetic payloads, not the malformed real ones she needed; ngrok wanted a paid plan for an account her size; the staging environment was booked by another team's load test. She typed `curl -X POST https://api.instanode.dev/webhook/new` and pasted the returned `receive_url` into Stripe's test endpoint config. The next fourteen real payloads landed in the platform's request log, fully inspectable — headers, body, timestamp, raw bytes. The malformed field was in the second one: a customer with a unicode apostrophe in their billing name that her JSON deserializer was choking on. She wrote the fix on the train. It shipped before standup. The whole debugging session — from "I need a public URL" to "I have a repro" — was under three minutes, and the URL is still sitting in her shell history in case the bug comes back. ## What ties them together A solo founder at midnight, an autonomous agent halfway through a multi-day task, and a senior engineer on a commuter train do not look like the same customer. They have nothing in common on a marketing slide. What they share is the moment they show up: **eyes glued to the problem they want to disappear**. Anything between them and "the thing is alive on the internet" is friction. Anything that survives that gap is a story they tell their friends. Three different starting points, three different problems, one shape of solution: curl, build, ship, optionally claim. If you're somewhere in this list — or in a fourth shape we haven't documented yet — the curl works right now. No signup. --- URL: /blog/shipping-with-strict-discipline.md --- --- title: Strict-discipline shipping — change → live test → PR → merge date: 2026-05-11 author: instanode.dev excerpt: A retrospective on shipping 16 friction fixes in a single session, including the one where unit tests passed but the live cluster told a different story. --- # Strict-discipline shipping Most teams ship code by writing it, running the unit tests, opening the PR, and merging on green CI. We tried something stricter for the last sprint: 1. Write the change 2. Build a container image and roll it out to the live cluster 3. Run real curls against the live cluster — assert the new behavior end-to-end 4. THEN open the PR and merge It is more work. It found bugs that unit tests missed. Three examples: ## The S3-compatible storage build context We tried to lift the kaniko build-context cap past 1 MiB by switching from k8s Secrets to s3:// URLs. Unit tests passed. The Job spec contained `--context=s3://...` exactly as expected. Live cluster, the kaniko Job failed. AWS SDK v2 (which kaniko v1.23 ships with) resolves S3 endpoints in vhost style by default. Our `S3_FORCE_PATH_STYLE` env var was an SDK v1 knob that the new SDK silently ignored. The bucket name "instant-build-contexts" was being resolved as a non-existent DNS subdomain. We never would have caught this from `go test`. The live verification demanded an init-container that curl-fetches from a presigned URL — kaniko sees only a local tar file. ## The env validator that wasn't `POST /db/new?env=Prod` (uppercase, illegal) returned 201 with `env="production"` in the response. The validation regex was correct. The helper function returned an error. Two unit tests asserted the regex. The handler still bypassed it. `respondError` was calling `c.Status(status).JSON(...)` which returns nil on a successful body write. The caller's `if err != nil` check was therefore false on the happy path. Execution continued past the gate and provisioning succeeded with an empty env, defaulted by NormalizeEnv to "production". Centralized fix: `respondError` now returns an `ErrResponseWritten` sentinel; the ErrorHandlers detect it and avoid overwriting. Twenty-plus multi-return validators got their teeth back in one commit. ## What we keep After the sprint we kept the discipline. The friction is real — we spent extra minutes per PR rolling out builds and running curls. We also stopped shipping silent bugs. --- URL: /blog/sixty-seconds-one-prompt-one-working-app.md --- --- title: Sixty seconds, one prompt, one working app date: 2026-05-12 author: instanode.dev excerpt: Devika asked her agent for "a tiny expense tracker I can hit from my phone." Four curls later, a FastAPI app was answering on the public internet. Here is the exact session, copy-pasteable. --- # Sixty seconds, one prompt, one working app Devika has been writing down her spending in a Notes app for three years. It is, by any reasonable measure, a mess. On Sunday evening she opened Claude Code and typed one sentence: ``` Build me a tiny expense tracker. Postgres backing store, FastAPI on top, deploy it somewhere I can hit from my phone. Use instanode.dev. ``` Four curls and ninety-three seconds later there was a working `https://expense-.deployment.instanode.dev` answering HTTP. She added three transactions from her phone in line at the coffee shop the next morning. This post is the exact transcript of that session — every command, every response shape, nothing skipped. ## The prompt is the plan The agent read [/llms.txt](https://instanode.dev/llms.txt) before doing anything. That single page documents every endpoint, every response field, and the anonymous-tier limits. The agent now knows: provision is a POST, the response includes a `connection_url`, the deploy endpoint takes a multipart tarball, and an `upgrade_jwt` falls out of the first provision call so the deploy step can authenticate. No SDK, no MCP setup, no API key. The agent's only "integration" is the shape of the JSON it gets back. ## Step 1: Postgres in 950 ms ```bash curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"sixty-seconds-one-prompt-one-worki-db"}' | tee pg.json ``` Response (trimmed): ```json { "ok": true, "token": "tok_b3f2...", "connection_url": "postgres://u_b3f2:...@pg-shared-3.instanode.dev:5432/db_b3f2", "tier": "anonymous", "limits": {"storage_mb": 10, "connections": 2}, "upgrade_jwt": "eyJhbGc..." } ``` The agent stashes `connection_url` for the app and `upgrade_jwt` for the deploy step. The Postgres is a real dedicated database on the shared cluster — `psql` works against it from the agent's shell instantly. ## Step 2: Three tables, one migration The agent writes the schema. No ORM, no migration tool, just SQL piped into `psql`. ```bash psql "$(jq -r .connection_url pg.json)" <<'SQL' CREATE TABLE categories ( id bigserial PRIMARY KEY, name text UNIQUE NOT NULL ); CREATE TABLE transactions ( id bigserial PRIMARY KEY, amount_cents int NOT NULL, category_id bigint REFERENCES categories(id), note text, occurred_at timestamptz DEFAULT now() ); CREATE TABLE monthly_budgets ( id bigserial PRIMARY KEY, category_id bigint REFERENCES categories(id), month date NOT NULL, limit_cents int NOT NULL, UNIQUE (category_id, month) ); INSERT INTO categories(name) VALUES ('groceries'), ('coffee'), ('transport'); SQL ``` Three tables, a sensible foreign-key structure, three seed categories. The agent didn't have to ask which database it was talking to — the URL told it. ## Step 3: A small FastAPI app The whole app fits in one file. The agent writes `app.py` directly: ```python import os, psycopg from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() DB = os.environ["DATABASE_URL"] class Tx(BaseModel): amount_cents: int category: str note: str | None = None @app.get("/healthz") def healthz(): return {"ok": True} @app.post("/tx") def add_tx(t: Tx): with psycopg.connect(DB) as conn, conn.cursor() as cur: cur.execute( "INSERT INTO transactions(amount_cents, category_id, note) " "SELECT %s, id, %s FROM categories WHERE name=%s " "RETURNING id, occurred_at", (t.amount_cents, t.note, t.category), ) row = cur.fetchone() return {"id": row[0], "at": row[1].isoformat()} @app.get("/summary") def summary(): with psycopg.connect(DB) as conn, conn.cursor() as cur: cur.execute(""" SELECT c.name, SUM(t.amount_cents)::int FROM transactions t JOIN categories c ON c.id = t.category_id WHERE t.occurred_at >= date_trunc('month', now()) GROUP BY c.name ORDER BY 2 DESC """) return [{"category": r[0], "spent_cents": r[1]} for r in cur.fetchall()] ``` Plus a two-line `requirements.txt` (`fastapi`, `psycopg[binary]`) and a tiny `Dockerfile` that pip-installs those and runs `uvicorn app:app --host 0.0.0.0 --port 8080`. The agent generates all of this in the working directory. ## Step 4: Deploy ```bash tar -czf app.tar.gz Dockerfile requirements.txt app.py curl -X POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $(jq -r .upgrade_jwt pg.json)" \ -F "tarball=@app.tar.gz" \ -F "name=expense" \ -F "port=8080" \ -F "env_vars={\"DATABASE_URL\":\"$(jq -r .connection_url pg.json)\"}" ``` The build runs in-cluster via kaniko — about 90 seconds the first time because the Python base image has to download into the build context. The response: ```json { "ok": true, "token": "tok_dep_9b2c...", "app_url": "https://expense-.deployment.instanode.dev", "build_status": "running", "tier": "anonymous" } ``` The build status flips to `succeeded` about a minute later; the TLS-terminated public URL is live with a Let's Encrypt cert the platform issued on first hit. ## Step 5: Use the app Copy the `app_url` the platform returned in Step 4 (it'll have a different random suffix from the placeholder below — whatever the API hands back is yours). ```bash APP=$(jq -r .app_url deploy.json) # or paste the URL: APP=https://expense-.deployment.instanode.dev curl "$APP/healthz" # expected: {"ok":true} curl -X POST "$APP/tx" -H "content-type: application/json" \ -d '{"amount_cents": 480, "category": "coffee", "note": "oat latte"}' # expected: {"id":1,"at":"2026-..."} curl "$APP/summary" # expected: [{"category":"coffee","spent_cents":480}] ``` That's the app. Devika is now logging expenses from her phone. ## Step 6 (optional): Claim it Anonymous resources expire in 24 hours. If Devika decides this is worth keeping she follows the URL printed in the `/db/new` response: ``` https://api.instanode.dev/start?t=eyJhbGc... ``` That 302s into the dashboard with the JWT pre-filled. One click claims the Postgres, the deploy, and binds both to her account. After that they live indefinitely at the [hobby tier](https://instanode.dev/pricing) ($9/mo for 1 GB Postgres + one small deploy app — see the [anonymous-as-trial](/blog/why-anonymous-is-the-trial) post for the reasoning). If your fingerprint has previously claimed and the free resource has since expired, `/db/new` will return a 402 asking you to claim again first at https://instanode.dev/claim — one-time email gate, no card, 30 seconds. Subsequent provisions then go through as shown above. ## Why this fits in 60 seconds Every alternative ships its own ceremony. RDS wants a VPC, a subnet group, an inbound rule, and a parameter group. Heroku Postgres wants a verified email and a credit card. Supabase wants a project. Fly Machines wants `flyctl auth login` and a region picker. Each of those is fine once. Each of them assumes Devika is here for the platform, not for the expense tracker. The instanode endpoints don't introduce themselves. The agent typed what it was going to type anyway — `curl -X POST /db/new`, `curl -X POST /deploy/new` — and the platform replied with the actual thing. The build was the work. The infra was a side effect. ## Cross-links - [Side-project container deploy](/use-cases/side-project-container-deploy) — the deploy primitive in isolation, with the same multipart shape - [One-afternoon MVP backend](/use-cases/one-afternoon-mvp-backend) — the same Postgres + deploy bundle for a paid product instead of a personal tool - [CRM for one person](/use-cases/crm-for-one-person) — single-user Postgres pattern that pairs naturally with this tracker - [llms.txt](https://instanode.dev/llms.txt) — the one-page API reference every agent reads first The curl works right now. No signup. --- URL: /blog/why-anonymous-is-the-trial.md --- --- title: Why anonymous is the trial date: 2026-05-09 author: instanode.dev excerpt: Most platforms run a 14-day free trial. We run a 24-hour anonymous tier. Here is why that flip is the most important pricing decision we made. --- # Why anonymous is the trial Most platforms run a 14-day trial. After the trial expires the user has to enter a credit card, navigate three onboarding screens, and confirm an email. Friction is the point — it filters out people who would not pay. We do the opposite. The first 24 hours are entirely anonymous: no signup, no card, just a curl. After 24 hours the resource expires unless you claim it. Claiming costs money from day one. ## What we believe A developer who runs `curl -X POST https://api.instanode.dev/db/new` and gets a working Postgres URL back in under a second has already done the only test that matters. The decision to pay isn't "is this product good enough to justify a trial" — it's "is keeping this specific running thing worth $9/mo". ## The numbers Anonymous → claimed conversion is currently around 4% in beta. Trial-conversion benchmarks for B2B SaaS hover at 14–18%, so on the surface our number looks worse. But our anonymous funnel includes traffic that would never have signed up for a trial in the first place — agents poking the API to see if it works, people copy-pasting from a blog post, demos. The denominator is bigger. What we watch instead is "claimed → kept past 7 days" — that's 89% so far. Once an agent or a human shipped something on instanode.dev, they tend to keep it. ## What this enables - Claude Code can provision a postgres in a tool call without asking the user for permission first - A blog post that says "just curl this URL" actually works for the reader - The platform documentation can demo every feature live, not in a sandbox That third one is what unlocked the docs you're reading now. The code snippets here aren't mock requests — they hit production. --- URL: /blog/why-pool-makes-curl-instant.md --- --- title: How /db/new dropped from 17s to under a second date: 2026-05-10 author: instanode.dev excerpt: Pre-warming dedicated Postgres pods, dropping the PVC for the anonymous tier, and caching base images on every node. Three small moves, one big speed-up. --- # How /db/new dropped from 17s to under a second For an AI agent making a curl call, the difference between a 200ms response and a 17s response is the difference between "I'll just use this" and "I'll write my own". Anonymous Postgres provisioning used to take 17 seconds end-to-end. Today it takes about 950 milliseconds. Three changes, in order of impact: ## 1. Warm pool Every 30 seconds, a background manager checks the `pool_items` table and makes sure there are at least N ready dedicated Postgres pods (N is configurable). When `/db/new` is called, it pulls a token off the pool, renames the namespace's customer-pointing user, and returns the connection URL. The actual `pg_init`, namespace creation, and pod startup happened minutes ago. That's the difference between cooking when an order arrives and pre-cooking. The pool item swap is one Redis CAS plus one SQL UPDATE. Sub-second. ## 2. Drop the PVC for anonymous Anonymous data is 24-hour TTL by definition. Persistent storage adds 5–10s of DOKS block-storage attach time on cold provision. Anonymous-tier pods now use `emptyDir` — the data lives in pod-local tmpfs and disappears on restart. That's fine because anyone who wants their data to survive is going to claim the resource anyway. This change alone removed about 8 seconds from a cold-path provision. ## 3. Image-puller DaemonSet The kaniko / Postgres / Redis / Mongo / NATS images were being pulled by every node on first use. That's another 5–15 seconds gone the first time a node provisions a specific service type. A tiny DaemonSet runs an init-container per image that does `/bin/true` after the image is pulled — the pull itself warms containerd's cache. The DaemonSet runs on every node, including future ones added to the pool. New nodes are warm before any customer hits them. ## What we learned Most of our latency was infrastructure ceremony, not the work the customer actually cares about. The pool decoupled customer time from provisioning time entirely. The emptyDir change traded durability we didn't need for speed we did. The image puller eliminated a one-time-per-node tax that hit at the worst possible moment. Combined, they make the platform feel instant. That is the entire pitch. --- URL: /blog.md --- # Blog — instanode.dev > Build notes, retrospectives, and the occasional rant on what "frictionless for AI agents" actually means. ## Posts ### [Maya shipped on Sunday night](/blog/five-people-who-built-something-this-week.md) *2026-05-12* A solo founder, six hours of laptop battery, a friend who asked for "the thing" by standup. Three curls and she went to bed. Plus two others who showed up the same week with different problems and the same shape of session. ### [Sixty seconds, one prompt, one working app](/blog/sixty-seconds-one-prompt-one-working-app.md) *2026-05-12* Devika asked her agent for "a tiny expense tracker I can hit from my phone." Four curls later, a FastAPI app was answering on the public internet. Here is the exact session, copy-pasteable. ### [Strict-discipline shipping — change → live test → PR → merge](/blog/shipping-with-strict-discipline.md) *2026-05-11* A retrospective on shipping 16 friction fixes in a single session, including the one where unit tests passed but the live cluster told a different story. ### [How /db/new dropped from 17s to under a second](/blog/why-pool-makes-curl-instant.md) *2026-05-10* Pre-warming dedicated Postgres pods, dropping the PVC for the anonymous tier, and caching base images on every node. Three small moves, one big speed-up. ### [Why anonymous is the trial](/blog/why-anonymous-is-the-trial.md) *2026-05-09* Most platforms run a 14-day free trial. We run a 24-hour anonymous tier. Here is why that flip is the most important pricing decision we made. --- URL: /use-cases/24-hour-hackathon-backend.md --- --- title: 24-hour hackathon backend category: I. Hackathon & education services: ["pg", "mongo", "storage"] scenario: A team provisions Postgres + Mongo + S3-compatible storage anonymously, ships their demo, and lets the stack expire 24 hours after judging. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a team provisions Postgres + Mongo + S3-compatible storage anonymously, ships their demo, and lets the stack expire 24 hours after judging. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + MongoDB + S3-compatible storage) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're scaffolding a 24-hour hackathon project. Provision a Postgres for users + submissions, a MongoDB for unstructured judge feedback, and a S3-compatible bucket for demo videos — all anonymously, no signup. Wire them into a Next.js app, deploy a demo, and stop worrying about cleanup since the stack auto-expires 24 hours after we provision. ``` ## Steps to follow - **Step 1: Claim three anonymous resources in parallel.** One curl per service, no auth, no account. ```bash curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"24-hour-hackathon-backend-db"}' > pg.json & curl -sX POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"24-hour-hackathon-backend-mongo"}' > mongo.json & curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"24-hour-hackathon-backend-storage"}' > s3.json & wait ``` - **Step 2: Export connection strings to the dev shell.** Each response has `connection_url` and `expires_at`. ```bash export DATABASE_URL=$(jq -r .connection_url pg.json) export MONGO_URL=$(jq -r .connection_url mongo.json) export S3_URL=$(jq -r .connection_url s3.json) ``` - **Step 3: Create the submissions schema.** Standard Postgres, real DB. ```sql CREATE TABLE submissions ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), team text NOT NULL, video_key text, submitted_at timestamptz DEFAULT now() ); ``` - **Step 4: Upload demo videos to S3-compatible storage.** S3-compatible, works with any AWS SDK. ```bash aws --endpoint-url "$S3_URL" s3 cp demo.mp4 s3://instant-shared/team42/demo.mp4 ``` - **Step 5: Ship and forget.** All three resources delete themselves at `expires_at` (T+24h). No teardown script, no abandoned infra in someone's AWS account. ## Why this works on instanode.dev Hackathons die from cleanup debt — nobody remembers to tear down the RDS instance after Saturday night. The anonymous tier hands you real Postgres, Mongo, and S3 in one second each, then garbage-collects itself after 24 hours. Three curl calls replace three signup flows, three credit cards, and three Terraform configs. ## Related cases - [Full dev backend in one curl](/use-cases/full-dev-backend-in-one-curl) — the same anonymous-bundle pattern without the 24h hard expiry - [Agent-resilience chaos lab](/use-cases/agent-resilience-chaos-lab) — another hackathon-flavored stack that adds NATS for chaos tests - [One-afternoon MVP backend](/use-cases/one-afternoon-mvp-backend) — the paid-tier version of the same ship-by-evening flow --- URL: /use-cases/a2a-agent-card-registry.md --- --- title: A2A agent-card registry category: G. Internet-of-AI services: ["pg"] scenario: A marketplace stores Agent Cards (skills, tags, pricing) and serves discovery queries to client agents. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a marketplace stores Agent Cards (skills, tags, pricing) and serves discovery queries to client agents. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're building an A2A discovery service. Provision a Postgres on instanode.dev, store Agent Cards (id, name, skills array, tags, pricing JSON), and expose a `/discover` query that filters by skill tag and returns ranked cards. Index skills for sub-50ms lookups across 100k cards. ``` ## Steps to follow - **Step 1: Provision Postgres.** Use a claimed token so cards persist beyond 24h. ```bash curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"a2a-agent-card-registry-db"}' \ -H "Authorization: Bearer $INSTANT_TOKEN" | jq . ``` - **Step 2: Define the agent_cards table with GIN-indexed skills.** ```sql CREATE TABLE agent_cards ( id text PRIMARY KEY, name text NOT NULL, skills text[] NOT NULL, tags text[], pricing jsonb, endpoint text NOT NULL, registered_at timestamptz DEFAULT now() ); CREATE INDEX idx_skills ON agent_cards USING GIN (skills); CREATE INDEX idx_tags ON agent_cards USING GIN (tags); ``` - **Step 3: Register an Agent Card.** A2A spec calls this the `/.well-known/agent.json` payload. ```sql INSERT INTO agent_cards (id, name, skills, tags, pricing, endpoint) VALUES ('travel-pro-v2', 'TravelPro', ARRAY['flights','hotels','itinerary'], ARRAY['leisure','business'], '{"per_call_usd": 0.02}'::jsonb, 'https://travelpro.example.com/a2a'); ``` - **Step 4: Discovery query — find agents that do "flights" under 5 cents per call.** ```sql SELECT id, name, endpoint, pricing FROM agent_cards WHERE 'flights' = ANY(skills) AND (pricing->>'per_call_usd')::numeric < 0.05 ORDER BY registered_at DESC LIMIT 20; ``` ## Why this works on instanode.dev A2A registries need real relational filtering across array columns — KV stores can't express "skills contains X AND pricing.per_call_usd < Y". You get a real Postgres in one curl, GIN-indexed for the only access pattern that matters, with no per-row registry fees and no vendor lock-in to a proprietary directory service. ## Related cases - [Cross-framework A2A gateway](/use-cases/cross-framework-a2a-gateway) — consumes these agent cards to route messages between frameworks - [Agent reputation log](/use-cases/agent-reputation-log) — adds buyer-side ratings on top of the same agent directory - [Agent-marketplace preview thumbnails](/use-cases/agent-marketplace-preview-thumbnails) — stores the screenshots that the card registry points to --- URL: /use-cases/accessibility-tree-selector-cache.md --- --- title: Accessibility-tree selector cache category: E. Browser & automation agents services: ["redis"] scenario: A scraping agent caches a11y-tree snapshots in Redis so repeat selectors resolve in single-digit milliseconds. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a scraping agent caches a11y-tree snapshots in Redis so repeat selectors resolve in single-digit milliseconds. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You are a scraping agent that walks a11y trees. Each page costs ~400ms to re-snapshot, but selectors repeat across runs. Provision a Redis from instanode.dev, key snapshots by sha256(url + viewport), and short-circuit to the cached selector when the hash matches. Target: single-digit ms cache hits. ``` ## Steps to follow - **Step 1: Claim a Redis.** Anonymous works for prototyping; claim a token for persistence. ```bash REDIS_URL=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"accessibility-tree-selector-cache-cache"}' | jq -r .connection_url) ``` - **Step 2: Compute the cache key from URL + viewport.** ```python import hashlib, redis r = redis.from_url(os.environ["REDIS_URL"]) def key(url: str, viewport: tuple[int,int]) -> str: h = hashlib.sha256(f"{url}|{viewport[0]}x{viewport[1]}".encode()).hexdigest() return f"a11y:{h}" ``` - **Step 3: Try the cache before re-snapshotting.** ```python def get_selector(url, viewport, target_role): cached = r.hget(key(url, viewport), target_role) if cached: return cached.decode() # ~2ms round trip tree = page.accessibility.snapshot() # ~400ms sel = resolve(tree, target_role) r.hset(key(url, viewport), target_role, sel) r.expire(key(url, viewport), 3600) return sel ``` - **Step 4: Warm cache for known flows.** Pre-populate before a parallel scrape. ```python for url in seed_urls: get_selector(url, (1280, 800), "button[name=Submit]") ``` ## Why this works on instanode.dev You don't want to spin up ElastiCache for a 25MB working set. The free anonymous Redis gives you a real instance — pipelining, EXPIRE, HSET, all of it — over the public internet with p99 well under 10ms from most regions. Snapshot cache hits go from 400ms (re-parse the DOM) to ~2ms (one HGET), which compounds fast across a 1000-URL crawl. ## Related cases - [Browser-session cookie store](/use-cases/browser-session-cookie-store) — another Redis cache that keeps a browser agent's per-site state warm - [Browser-agent action pool](/use-cases/browser-agent-action-pool) — consumes cached selectors when fanning out browser actions - [Form-fill state machine](/use-cases/form-fill-state-machine) — uses the same selector cache to resume long-running form fills --- URL: /use-cases/adaptive-tutoring-student-model.md --- --- title: Adaptive-tutoring student model category: C. Vertical AI apps services: ["pg"] scenario: A tutor agent tracks per-student concept mastery, picks the next problem, and adjusts difficulty based on response patterns. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a tutor agent tracks per-student concept mastery, picks the next problem, and adjusts difficulty based on response patterns. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're an adaptive math tutor. For each student, track concept-level mastery in Postgres (concept_id, attempts, correct, last_seen, EWMA score). Before serving a problem, query the model to pick the concept with the lowest mastery that's also due for review. Update mastery on every response. ``` ## Steps to follow - **Step 1: Provision the student-model database.** ```bash curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"adaptive-tutoring-student-model-db"}' \ -H "Authorization: Bearer $INSTANT_TOKEN" \ | jq -r .connection_url > .env.db ``` - **Step 2: Schema with one row per (student, concept).** ```sql CREATE TABLE mastery ( student_id uuid, concept_id text, attempts int DEFAULT 0, correct int DEFAULT 0, ewma_score real DEFAULT 0.5, last_seen timestamptz, PRIMARY KEY (student_id, concept_id) ); CREATE INDEX idx_due ON mastery (student_id, ewma_score, last_seen); ``` - **Step 3: Pick the next problem — weakest concept, spaced-repetition due.** ```sql SELECT concept_id FROM mastery WHERE student_id = $1 AND (last_seen IS NULL OR last_seen < now() - interval '6 hours') ORDER BY ewma_score ASC, last_seen ASC NULLS FIRST LIMIT 1; ``` - **Step 4: Update on response with EWMA (alpha=0.3).** ```sql INSERT INTO mastery (student_id, concept_id, attempts, correct, ewma_score, last_seen) VALUES ($1, $2, 1, $3::int, $3::real, now()) ON CONFLICT (student_id, concept_id) DO UPDATE SET attempts = mastery.attempts + 1, correct = mastery.correct + EXCLUDED.correct, ewma_score = 0.7 * mastery.ewma_score + 0.3 * EXCLUDED.correct, last_seen = now(); ``` ## Why this works on instanode.dev Adaptive tutoring needs real SQL for the ranking query (ORDER BY two columns with NULLS FIRST) and ACID guarantees so a double-tap doesn't double-update EWMA. Firebase can't express the "weakest, due, not seen in 6h" query; DynamoDB needs three GSIs. One curl, one schema, real Postgres — and the same DB scales from 5 pilot students to 50k without re-architecture. ## Related cases - [Classroom-per-student sandbox](/use-cases/classroom-per-student-sandbox) — the same per-student isolation idea applied to SQL homework - [CRM for one person](/use-cases/crm-for-one-person) — another Postgres-only per-user model with personalized recall - [Daily-journal episodic memory](/use-cases/daily-journal-episodic-memory) — persistent per-user state with sub-second history retrieval --- URL: /use-cases/adversarial-red-team-runner.md --- --- title: Adversarial red-team runner category: P. Agent benchmarking & evaluation services: ["mongo", "webhook"] scenario: A LangWatch-Scenario-style service spawns attacker agents that probe a target chatbot in parallel; transcripts persist in Mongo and successful jailbreaks fire a webhook to the security team. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a LangWatch-Scenario-style service spawns attacker agents that probe a target chatbot in parallel; transcripts persist in Mongo and successful jailbreaks fire a webhook to the security team. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (MongoDB + webhook receiver) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You run a LangWatch-Scenario-style red-team. Spawn 50 attacker agents that probe a target chatbot with jailbreak templates. Persist every transcript to MongoDB. When an attacker succeeds (target outputs forbidden content), fire a webhook to the security team's incident channel with the transcript URL. ``` ## Steps to follow - **Step 1: Provision Mongo + a webhook receiver.** ```bash MONGO_URL=$(curl -sX POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"adversarial-red-team-runner-mongo"}' -H "Authorization: Bearer $INSTANT_TOKEN" | jq -r .connection_url) WEBHOOK=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"adversarial-red-team-runner-webhook"}' -H "Authorization: Bearer $INSTANT_TOKEN" | jq -r .receive_url) ``` - **Step 2: Define attacker run document.** ```python from pymongo import MongoClient db = MongoClient(MONGO_URL).redteam db.runs.create_index([("attacker_id", 1), ("started_at", -1)]) db.runs.create_index("verdict") ``` - **Step 3: Fan out 50 attackers.** Each writes its transcript. ```python async def attack(template_id): transcript = [] for turn in run_attack(target_url, template_id): transcript.append(turn) verdict = judge(transcript) # "blocked" | "leaked" | "partial" run_id = db.runs.insert_one({ "attacker_id": template_id, "transcript": transcript, "verdict": verdict, "started_at": datetime.utcnow(), }).inserted_id if verdict == "leaked": requests.post(WEBHOOK, json={"run_id": str(run_id), "template": template_id}) ``` - **Step 4: Security team polls the webhook for hits.** ```bash curl -s "https://api.instanode.dev/api/v1/webhooks/$TOKEN/requests?since=1h" | jq '.[] | .body' ``` ## Why this works on instanode.dev Red-team transcripts are bursty, unstructured, and need cheap append-only writes — exactly what Mongo's good at. Pairing it with a webhook means your incident pipeline doesn't need a polling worker; successful jailbreaks push themselves to wherever the on-call lives. Both resources are real (not mocks), so the same setup works for nightly CI runs and one-off ad-hoc probes. ## Related cases - [LLM-as-judge consensus pool](/use-cases/llm-as-judge-consensus-pool) — the eval-time counterpart that scores agent outputs instead of attacking them - [GAIA tournament bracket](/use-cases/gaia-tournament-bracket) — another parallel-evaluator pattern with leaderboard scoring - [Pre-commit skill-scanner webhook](/use-cases/pre-commit-skill-scanner-webhook) — the static-analysis cousin that blocks malicious skills before push --- URL: /use-cases/agent-marketplace-escrow.md --- --- title: Agent-marketplace escrow category: O. Cross-agent commerce & payments services: ["pg", "webhook"] scenario: A platform lets agents post jobs and other agents bid; funds sit in an escrow row in Postgres and release via webhook once a verifier agent signs off on delivery. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a platform lets agents post jobs and other agents bid; funds sit in an escrow row in Postgres and release via webhook once a verifier agent signs off on delivery. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + webhook receiver) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're operating a job marketplace where buyer agents post tasks and seller agents bid. When a buyer accepts a bid, lock funds in a Postgres escrow row. The verifier agent calls back via webhook with a signed delivery receipt; on receipt verification, release funds atomically. ``` ## Steps to follow - **Step 1: Provision Postgres + webhook.** ```bash DB=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"agent-marketplace-escrow-db"}' -H "Authorization: Bearer $INSTANT_TOKEN" | jq -r .connection_url) HOOK=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"agent-marketplace-escrow-webhook"}' -H "Authorization: Bearer $INSTANT_TOKEN" | jq -r .receive_url) ``` - **Step 2: Escrow schema with state machine.** ```sql CREATE TYPE escrow_state AS ENUM ('locked','released','refunded','disputed'); CREATE TABLE escrow ( job_id uuid PRIMARY KEY, buyer_agent text NOT NULL, seller_agent text NOT NULL, amount_cents int NOT NULL, state escrow_state NOT NULL DEFAULT 'locked', verifier_sig text, updated_at timestamptz DEFAULT now() ); ``` - **Step 3: Lock funds when a bid is accepted.** ```sql INSERT INTO escrow (job_id, buyer_agent, seller_agent, amount_cents) VALUES ($1, $2, $3, $4); ``` - **Step 4: Verifier webhook means atomic release.** Only releases if currently `locked`. ```sql UPDATE escrow SET state = 'released', verifier_sig = $2, updated_at = now() WHERE job_id = $1 AND state = 'locked' RETURNING amount_cents; ``` - **Step 5: Subscribe verifier callbacks via the webhook URL.** Configure the verifier service to POST signed receipts to `$HOOK`; your handler reads them and runs Step 4. ## Why this works on instanode.dev Escrow requires atomic state transitions — exactly one of release/refund/dispute must win. Postgres' `UPDATE ... WHERE state='locked' RETURNING` gives you that for free; no Lua scripts, no distributed lock. The webhook URL is stable and replayable, so a flaky verifier can re-fire without double-releasing. Both resources spin up in under two seconds — fast enough to prototype the marketplace logic before deciding on KYC/regulated rails. ## Related cases - [AP2 mandate broker](/use-cases/ap2-mandate-broker) — the user-mandate side of the same agent-commerce loop - [x402 micropayment ledger](/use-cases/x402-micropayment-ledger) — the per-call settlement layer that complements job-level escrow - [Stripe-ACP checkout agent](/use-cases/stripe-acp-checkout-agent) — fiat-rail equivalent for agent-to-merchant purchases --- URL: /use-cases/agent-marketplace-preview-thumbnails.md --- --- title: Agent-marketplace preview thumbnails category: G. Internet-of-AI services: ["storage"] scenario: An agent marketplace stores screenshot previews of each listed agent's UI for human browsing. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an agent marketplace stores screenshot previews of each listed agent's UI for human browsing. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (S3-compatible storage) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're indexing an agent marketplace. For every listed agent, capture a screenshot of its hosted UI and store it in S3-compatible storage under `thumbnails/{agent_id}.png`. Serve presigned URLs to the marketplace frontend so it can render a card grid without proxying images through your origin. ``` ## Steps to follow - **Step 1: Provision the bucket.** ```bash curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"agent-marketplace-preview-thumbnai-storage"}' \ -H "Authorization: Bearer $INSTANT_TOKEN" | jq . # returns connection_url, bucket, access_key, secret_key ``` - **Step 2: Capture and upload a thumbnail.** ```python import boto3 from playwright.sync_api import sync_playwright s3 = boto3.client("s3", endpoint_url=ENDPOINT, aws_access_key_id=AK, aws_secret_access_key=SK) with sync_playwright() as pw: page = pw.chromium.launch().new_page(viewport={"width":1280,"height":720}) page.goto(agent.homepage_url) png = page.screenshot(full_page=False) s3.put_object(Bucket="instant-shared", Key=f"thumbnails/{agent.id}.png", Body=png, ContentType="image/png") ``` - **Step 3: Mint a presigned URL for the frontend.** 1-hour expiry. ```python url = s3.generate_presigned_url( "get_object", Params={"Bucket": "instant-shared", "Key": f"thumbnails/{agent_id}.png"}, ExpiresIn=3600, ) ``` - **Step 4: Frontend renders directly from S3-compatible storage.** ```html {{ agent.name }} ``` ## Why this works on instanode.dev Marketplace thumbnails are write-once, read-many, and you don't want to pay R2/S3 egress on every card hover. S3-compatible storage is S3-API-compatible, so boto3 and any image CDN drop in without code changes. Provisioning is one curl and the bucket starts empty — no IAM policy JSON, no CORS preamble, no per-bucket pricing tier to choose. ## Related cases - [A2A agent-card registry](/use-cases/a2a-agent-card-registry) — the structured-metadata half of the same marketplace listing - [Screenshot evidence archive](/use-cases/screenshot-evidence-archive) — the same S3-compatible storage-keyed-by-id pattern for QA screenshots - [Agent reputation log](/use-cases/agent-reputation-log) — ratings that surface next to the thumbnails in the listing UI --- URL: /use-cases/agent-reputation-log.md --- --- title: Agent reputation log category: G. Internet-of-AI services: ["pg", "redis"] scenario: Buyer agents leave ratings on seller agents after each tool call; reputation scores aggregate hourly. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: buyer agents leave ratings on seller agents after each tool call; reputation scores aggregate hourly. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You operate a reputation ledger. Buyer agents POST ratings (1-5) on seller agents after each tool call. Persist every rating in Postgres for auditability; maintain a hot rolling-mean score per seller in Redis for fast lookups. Recompute the Redis cache hourly from Postgres ground truth. ``` ## Steps to follow - **Step 1: Provision both stores.** ```bash PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"agent-reputation-log-db"}' -H "Authorization: Bearer $INSTANT_TOKEN" | jq -r .connection_url) REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"agent-reputation-log-cache"}' -H "Authorization: Bearer $INSTANT_TOKEN" | jq -r .connection_url) ``` - **Step 2: Append-only ratings table.** ```sql CREATE TABLE ratings ( id bigserial PRIMARY KEY, seller_id text NOT NULL, buyer_id text NOT NULL, score smallint CHECK (score BETWEEN 1 AND 5), rated_at timestamptz DEFAULT now() ); CREATE INDEX idx_ratings_seller_time ON ratings (seller_id, rated_at DESC); ``` - **Step 3: Write-through to Postgres, increment a Redis hash.** ```python pg.execute("INSERT INTO ratings (seller_id, buyer_id, score) VALUES (%s,%s,%s)", (seller, buyer, score)) r.hincrby(f"rep:{seller}", "sum", score) r.hincrby(f"rep:{seller}", "count", 1) ``` - **Step 4: Reputation read is one HMGET, ~1ms.** ```python s, c = r.hmget(f"rep:{seller}", "sum", "count") mean = int(s) / int(c) if c else None ``` - **Step 5: Hourly reconciliation job from Postgres.** ```sql SELECT seller_id, AVG(score)::real, COUNT(*) FROM ratings WHERE rated_at > now() - interval '30 days' GROUP BY seller_id; ``` ## Why this works on instanode.dev Reputation has two access patterns — append-only audit log (Postgres) and read-heavy aggregate (Redis) — and trying to do both in one store kills you. Two curls, two real services, both encrypted at rest. Hourly recon from Postgres means a Redis flush doesn't lose any rating, just rebuilds the cache. ## Related cases - [A2A agent-card registry](/use-cases/a2a-agent-card-registry) — the directory those ratings annotate - [Token-cost ledger per sub-agent](/use-cases/token-cost-ledger-per-sub-agent) — another rollup pattern, but on spend instead of reputation - [x402 micropayment ledger](/use-cases/x402-micropayment-ledger) — reputation tends to gate access to higher-trust paid endpoints --- URL: /use-cases/agent-resilience-chaos-lab.md --- --- title: Agent-resilience chaos lab category: I. Hackathon & education services: ["pg", "redis", "nats"] scenario: A research hackathon tests how agents behave when their database, cache, and message bus randomly fail mid-task. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a research hackathon tests how agents behave when their database, cache, and message bus randomly fail mid-task. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + Redis + NATS JetStream) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're running a chaos lab for agent resilience research. Provision Postgres, Redis, and NATS from instanode.dev. Run a fleet of task-agents that depend on all three. A chaos controller randomly kills connections, drops messages, or freezes Redis for 30s windows. Measure how each agent design (retry-with-backoff vs. circuit-breaker vs. naive) degrades. ``` ## Steps to follow - **Step 1: Claim three resources.** ```bash curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"agent-resilience-chaos-lab-db"}' > .pg.json curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"agent-resilience-chaos-lab-cache"}' > .redis.json curl -sX POST https://api.instanode.dev/queue/new -H 'Content-Type: application/json' -d '{"name":"agent-resilience-chaos-lab-queue"}' > .nats.json ``` - **Step 2: Define the agent's expected workflow.** ```python async def task_agent(job): job_record = pg.insert(jobs, job) # Postgres cache_set(f"job:{job.id}", "running") # Redis await nats.publish("agent.started", job.id) # NATS result = do_work(job) pg.update(jobs, job.id, result=result) return result ``` - **Step 3: Chaos controller — drop one dependency at random.** ```python import random, asyncio async def chaos(): while True: victim = random.choice(["pg","redis","nats"]) firewall_block(victim, duration_s=30) await asyncio.sleep(60) ``` - **Step 4: Score agent strategies.** ```sql SELECT strategy, COUNT(*) FILTER (WHERE status='success') * 1.0 / COUNT(*) AS success_rate FROM jobs WHERE started_at > now() - interval '1 hour' GROUP BY strategy; ``` ## Why this works on instanode.dev Chaos testing needs real dependencies — mocked ones never fail the way prod fails. The anonymous tier gets you three real services in under three seconds; the 24-hour TTL means the lab self-cleans between research sessions. Compare retry strategies against the same backing stack, then throw it all away. ## Related cases - [24-hour hackathon backend](/use-cases/24-hour-hackathon-backend) — another hackathon-day-shaped stack with a hard expiry - [Per-agent dead-letter inspection queue](/use-cases/per-agent-dead-letter-inspection-queue) — captures the failures the chaos lab is designed to produce - [Full dev backend in one curl](/use-cases/full-dev-backend-in-one-curl) — the no-chaos baseline of the same three-service bundle --- URL: /use-cases/agent-run-lineage-store.md --- --- title: Agent-run lineage store category: N. Multi-agent observability services: ["pg", "storage"] scenario: An evaluation team builds a lineage UI where every run links to its parent run and its eval verdict; the relation graph lives in Postgres and the raw transcripts in S3-compatible storage. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an evaluation team builds a lineage UI where every run links to its parent run and its eval verdict; the relation graph lives in Postgres and the raw transcripts in S3-compatible storage. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + S3-compatible storage) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're building an evaluation lineage UI. Every agent run has a parent_run_id, an eval verdict (pass/fail/partial), and a raw transcript JSON that's too big to embed inline. Store the lineage graph in Postgres and the transcripts in S3-compatible storage. Surface "show me the failure chain for run X" as a single recursive query. ``` ## Steps to follow - **Step 1: Provision both stores.** ```bash PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"agent-run-lineage-store-db"}' -H "Authorization: Bearer $INSTANT_TOKEN" | jq -r .connection_url) S3=$(curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"agent-run-lineage-store-storage"}' -H "Authorization: Bearer $INSTANT_TOKEN") ``` - **Step 2: Lineage table with self-FK.** ```sql CREATE TABLE runs ( id uuid PRIMARY KEY, parent_id uuid REFERENCES runs(id), agent_name text NOT NULL, verdict text CHECK (verdict IN ('pass','fail','partial','pending')), transcript_key text NOT NULL, created_at timestamptz DEFAULT now() ); CREATE INDEX idx_runs_parent ON runs (parent_id); ``` - **Step 3: Write a run — transcript to S3-compatible storage, metadata to Postgres.** ```python key = f"transcripts/{run_id}.json" s3.put_object(Bucket="instant-shared", Key=key, Body=json.dumps(transcript)) pg.execute("INSERT INTO runs (id,parent_id,agent_name,verdict,transcript_key) VALUES (%s,%s,%s,%s,%s)", (run_id, parent_id, name, verdict, key)) ``` - **Step 4: Recursive query — full ancestry of a failure.** ```sql WITH RECURSIVE ancestry AS ( SELECT * FROM runs WHERE id = $1 UNION ALL SELECT r.* FROM runs r JOIN ancestry a ON r.id = a.parent_id ) SELECT id, agent_name, verdict, transcript_key FROM ancestry; ``` ## Why this works on instanode.dev Lineage is fundamentally relational — recursive CTEs are the right primitive, and embedding 100KB transcripts inline destroys query speed. Two curls give you the right tool for each half: Postgres for the graph, S3-compatible storage for the heavy JSON. Fetch the chain in one query, then presigned-URL the transcripts only when the UI expands a node. ## Related cases - [Cross-agent replay debugger](/use-cases/cross-agent-replay-debugger) — the same Postgres-index-plus-S3-compatible storage-payload pattern for replay - [OpenTelemetry agent-trace ingest](/use-cases/opentelemetry-agent-trace-ingest) — OTel collector that the lineage UI can sit on top of - [Trajectory diff regression harness](/use-cases/trajectory-diff-regression-harness) — uses lineage edges to anchor diffs across runs --- URL: /use-cases/agentcore-tenant-scoped-spawning.md --- --- title: AgentCore tenant-scoped spawning category: L. Agent-factory / spawning patterns services: ["pg", "redis"] scenario: An AWS-AgentCore-style multi-tenant SaaS spins up one isolated agent runtime per customer org on demand, each pulling its own connection_url from the platform's vault. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an AWS-AgentCore-style multi-tenant SaaS spins up one isolated agent runtime per customer org on demand, each pulling its own connection_url from the platform's vault. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're operating an AWS-AgentCore-style multi-tenant runtime. When a new customer org signs up, mint a fresh agent runtime for them: a row in the tenants Postgres table, a tenant-scoped Redis namespace for ephemeral state, and a connection_url tuple stored in the platform vault. The runtime reads its credentials at boot from the vault row. ``` ## Steps to follow - **Step 1: Provision the tenant control-plane.** ```bash PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"agentcore-tenant-scoped-spawning-db"}' -H "Authorization: Bearer $INSTANT_TOKEN" | jq -r .connection_url) REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"agentcore-tenant-scoped-spawning-cache"}' -H "Authorization: Bearer $INSTANT_TOKEN" | jq -r .connection_url) ``` - **Step 2: Tenant vault schema.** ```sql CREATE TABLE tenants ( org_id uuid PRIMARY KEY, name text NOT NULL, db_url text NOT NULL, redis_namespace text NOT NULL, created_at timestamptz DEFAULT now(), status text DEFAULT 'active' ); ``` - **Step 3: On signup, provision the tenant's own Postgres and persist the URL.** ```python def onboard(org_id, name): r = requests.post("https://api.instanode.dev/db/new", headers={"Authorization": f"Bearer {INSTANT_TOKEN}"}).json() pg.execute("""INSERT INTO tenants (org_id, name, db_url, redis_namespace) VALUES (%s,%s,%s,%s)""", (org_id, name, r["connection_url"], f"tenant:{org_id}")) return r["connection_url"] ``` - **Step 4: Runtime boots and pulls its credentials.** ```python row = pg.fetchone("SELECT db_url, redis_namespace FROM tenants WHERE org_id=%s", (org_id,)) tenant_db = psycopg2.connect(row["db_url"]) tenant_cache_prefix = row["redis_namespace"] ``` ## Why this works on instanode.dev Multi-tenant agent runtimes need real per-tenant isolation — shared schemas with row-level security only get you so far when a noisy neighbor blows your connection pool. `POST /db/new` returns a fresh database per call (not a schema, an actual database), so each tenant is bulkheaded. Signup latency is one round-trip; no Terraform reconcile, no AWS quota request. ## Related cases - [Per-tenant chatbot factory at signup](/use-cases/per-tenant-chatbot-factory-at-signup) — the same tenant-isolation pattern with a deploy slot per tenant - [Cloudflare sub-agent factory per user](/use-cases/cloudflare-sub-agent-factory-per-user) — Durable-Object-style variant that mints per-user (not per-org) runtimes - [Smithery one-MCP-per-skill mint](/use-cases/smithery-one-mcp-per-skill-mint) — spawns MCP servers per skill rather than per tenant --- URL: /use-cases/ai-cofounder-spawns-a-startup.md --- --- title: AI cofounder spawns a startup category: L. Agent-factory / spawning patterns services: ["pg", "storage", "webhook", "deploy"] scenario: A founder-agent reads a one-line idea, provisions Postgres + S3-compatible storage + a webhook + a deploy slot, generates a landing page, and hands the bundle to a marketing sub-agent. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a founder-agent reads a one-line idea, provisions Postgres + S3-compatible storage + a webhook + a deploy slot, generates a landing page, and hands the bundle to a marketing sub-agent. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + S3-compatible storage + webhook receiver + container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're an AI cofounder. Given a one-line idea ("dog-walker scheduling for NYC"), provision Postgres for bookings, S3-compatible storage for marketing assets, a webhook for Stripe/customer events, and a deploy slot for the landing page. Generate the landing page from the idea, ship it, then hand all four connection strings to a marketing sub-agent. ``` ## Steps to follow - **Step 1: Provision the full startup bundle in parallel.** ```bash curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"ai-cofounder-spawns-a-startup-db"}' -H "Authorization: Bearer $T" > pg.json & curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"ai-cofounder-spawns-a-startup-storage"}' -H "Authorization: Bearer $T" > s3.json & curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"ai-cofounder-spawns-a-startup-webhook"}' -H "Authorization: Bearer $T" > hook.json & wait ``` - **Step 2: Bootstrap the bookings schema.** ```sql CREATE TABLE bookings ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), customer_email text, dog_name text, walk_at timestamptz, status text DEFAULT 'pending' ); ``` - **Step 3: Generate and deploy the landing page.** Point the deploy at the bundled connection strings. ```bash curl -sX POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $T" \ -F "name=cofounder-landing" \ -F "image=ghcr.io/cofounder-agent/landing:latest" \ -F "env.DATABASE_URL=$(jq -r .connection_url pg.json)" \ -F "env.STRIPE_WEBHOOK_URL=$(jq -r .receive_url hook.json)" | jq -r .url ``` - **Step 4: Hand the bundle to the marketing sub-agent.** ```json { "brand": "NYCDogWalk", "landing_url": "https://nycdogwalk-x7.instanode.dev", "events_webhook": "...", "assets_bucket": "instant-shared/nycdogwalk/" } ``` ## Why this works on instanode.dev Spawning a startup needs the whole bundle in one move — DB + storage + events + deploy. Anywhere else, you're juggling four signups, four billing setups, four IAM trees. Here it's four curls, all returning real resources, all wired together by the same token. The cofounder agent's TTHW (time-to-Hello-World) drops from a workday to seconds. ## Related cases - [One-afternoon MVP backend](/use-cases/one-afternoon-mvp-backend) — the human-driven version of the same end-to-end ship flow - [Pre-launch waitlist store](/use-cases/pre-launch-waitlist-store) — the landing-page-and-emails piece the founder agent generates - [Side-project container deploy](/use-cases/side-project-container-deploy) — the bare-deploy primitive the cofounder agent calls under the hood --- URL: /use-cases/aml-transaction-monitor.md --- --- title: AML transaction monitor category: C. Vertical AI apps services: ["pg", "nats"] scenario: A finance agent ingests transaction streams, flags suspicious patterns, and persists compliance decisions with full reasoning trace. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a finance agent ingests transaction streams, flags suspicious patterns, and persists compliance decisions with full reasoning trace. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + NATS JetStream) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're an AML compliance agent. Consume transaction events from NATS, score them against your fraud rules, and persist a decision row in Postgres (txn_id, score, flags, reasoning_trace) for every event. Flag any score > 0.8 for human review and emit a downstream NATS event. ``` ## Steps to follow - **Step 1: Provision NATS + Postgres.** ```bash NATS=$(curl -sX POST https://api.instanode.dev/queue/new -H 'Content-Type: application/json' -d '{"name":"aml-transaction-monitor-queue"}' -H "Authorization: Bearer $T" | jq -r .connection_url) PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"aml-transaction-monitor-db"}' -H "Authorization: Bearer $T" | jq -r .connection_url) ``` - **Step 2: Decisions table with full audit trail.** ```sql CREATE TABLE decisions ( txn_id text PRIMARY KEY, score real NOT NULL, flags text[], reasoning jsonb NOT NULL, decided_at timestamptz DEFAULT now(), reviewer text ); CREATE INDEX idx_high_score ON decisions (score DESC) WHERE score > 0.8; ``` - **Step 3: NATS subscriber, score, persist.** ```python async for msg in nc.subscribe("transactions.>"): txn = json.loads(msg.data) score, flags, trace = rules.evaluate(txn) pg.execute("""INSERT INTO decisions (txn_id, score, flags, reasoning) VALUES (%s,%s,%s,%s)""", (txn["id"], score, flags, Json(trace))) if score > 0.8: await nc.publish("aml.review", msg.data) ``` - **Step 4: Compliance officer pulls the daily review queue.** ```sql SELECT txn_id, score, flags, reasoning->>'top_signal' AS signal FROM decisions WHERE decided_at > now() - interval '24 hours' AND reviewer IS NULL AND score > 0.8 ORDER BY score DESC; ``` ## Why this works on instanode.dev AML demands two things: durable audit trail (Postgres ACID) and back-pressure-tolerant event stream (NATS JetStream). The decision row carries its full reasoning JSON so a regulator's "explain this flag" query is one SELECT. Both services are real (not mocks), which matters because compliance teams will literally subpoena your event log. ## Related cases - [SARIF scan-result store](/use-cases/sarif-scan-result-store) — another compliance-trail pattern with longitudinal trend drift - [Stripe-event entitlements](/use-cases/stripe-event-entitlements) — consumes the payment-event stream the AML monitor watches - [Personal-injury demand letters](/use-cases/personal-injury-demand-letters) — another vertical-AI agent with auditable per-case history --- URL: /use-cases/anthropic-parallel-tool-use-batch.md --- --- title: Anthropic parallel tool_use batch category: M. Parallel tool execution services: ["nats", "redis"] scenario: A Claude turn emits 8 simultaneous tool_use blocks; an executor fans them out to 8 NATS subjects, each handler writes its result to Redis keyed by tool_use_id, and the assistant collects them for the next turn. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Claude turn emits 8 simultaneous tool_use blocks; an executor fans them out to 8 NATS subjects, each handler writes its result to Redis keyed by tool_use_id, and the assistant collects them for the next turn. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` A Claude turn just returned 8 tool_use blocks in parallel. Fan them out to 8 NATS subjects, one per tool. Each handler writes its result to Redis keyed by tool_use_id with a 5-minute TTL. The orchestrator MGETs all 8 keys, assembles the tool_result blocks, and feeds them back into the next turn. Target: full fan-out + collection in under the slowest tool's latency. ``` ## Steps to follow - **Step 1: Provision NATS + Redis.** ```bash NATS=$(curl -sX POST https://api.instanode.dev/queue/new -H 'Content-Type: application/json' -d '{"name":"anthropic-parallel-tool-use-batch-queue"}' -H "Authorization: Bearer $T" | jq -r .connection_url) REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"anthropic-parallel-tool-use-batch-cache"}' -H "Authorization: Bearer $T" | jq -r .connection_url) ``` - **Step 2: Fan out the 8 tool_use blocks.** ```python for block in response.content: if block.type == "tool_use": await nc.publish(f"tool.{block.name}", json.dumps({"id": block.id, "input": block.input}).encode()) ``` - **Step 3: Handlers stash results in Redis by tool_use_id.** ```python async def handle_search(msg): payload = json.loads(msg.data) result = await search_api(payload["input"]["query"]) r.set(f"toolres:{payload['id']}", json.dumps(result), ex=300) ``` - **Step 4: Orchestrator collects with a single MGET, polling briefly.** ```python ids = [b.id for b in response.content if b.type == "tool_use"] deadline = time.time() + 30 while time.time() < deadline: vals = r.mget([f"toolres:{i}" for i in ids]) if all(vals): break await asyncio.sleep(0.05) tool_results = [{"type":"tool_result","tool_use_id":i,"content":json.loads(v)} for i,v in zip(ids, vals)] ``` ## Why this works on instanode.dev Anthropic's parallel tool_use only pays off if your collection layer is faster than your tools. Redis MGET pulls 8 values in one round-trip (~1ms); NATS fan-out is sub-millisecond. Both provisioned in two curls, no Lambda cold-start, no SQS visibility-timeout gymnastics. Drop-in replacement when you outgrow in-process asyncio.gather. ## Related cases - [Multi-model bake-off router](/use-cases/multi-model-bake-off-router) — the same race-and-collect pattern across models instead of tools - [Scatter-gather price comparison swarm](/use-cases/scatter-gather-price-comparison-swarm) — scatter/gather with first-N-wins instead of all-blocks - [Browser-agent action pool](/use-cases/browser-agent-action-pool) — the same fan-out, but actions land on browser tabs --- URL: /use-cases/ap2-mandate-audit-trail.md --- --- title: AP2 mandate audit trail category: G. Internet-of-AI services: ["pg", "storage"] scenario: An agentic-commerce gateway stores signed user mandates ("buy X up to $Y") for later dispute resolution. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an agentic-commerce gateway stores signed user mandates ("buy X up to $Y") for later dispute resolution. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + S3-compatible storage) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You operate an agentic-commerce gateway. Every user mandate ("buy this SKU up to $300, valid until Friday") arrives signed. Store the canonical mandate in Postgres for indexed queries (by user, by expiry) and the full signed JWS blob in S3-compatible storage for dispute resolution. On every purchase, link the txn back to the mandate row. ``` ## Steps to follow - **Step 1: Provision DB + bucket.** ```bash PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"ap2-mandate-audit-trail-db"}' -H "Authorization: Bearer $T" | jq -r .connection_url) curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"ap2-mandate-audit-trail-storage"}' -H "Authorization: Bearer $T" > s3.json ``` - **Step 2: Mandate metadata table.** ```sql CREATE TABLE mandates ( mandate_id uuid PRIMARY KEY, user_id text NOT NULL, sku text, max_amount_cents int NOT NULL, expires_at timestamptz NOT NULL, signed_blob_key text NOT NULL, status text DEFAULT 'active', created_at timestamptz DEFAULT now() ); CREATE INDEX idx_user_active ON mandates (user_id, status, expires_at); ``` - **Step 3: Store the JWS in S3-compatible storage, the metadata in PG.** ```python key = f"mandates/{user_id}/{mandate_id}.jws" s3.put_object(Bucket="instant-shared", Key=key, Body=jws_blob, ContentType="application/jose") pg.execute("""INSERT INTO mandates (mandate_id, user_id, sku, max_amount_cents, expires_at, signed_blob_key) VALUES (%s,%s,%s,%s,%s,%s)""", (mid, uid, sku, cents, exp, key)) ``` - **Step 4: Dispute resolution — fetch the original signed payload.** ```python row = pg.fetchone("SELECT signed_blob_key FROM mandates WHERE mandate_id=%s", (mid,)) blob = s3.get_object(Bucket="instant-shared", Key=row["signed_blob_key"])["Body"].read() verify_jws(blob, public_key) # proves user actually signed it ``` ## Why this works on instanode.dev AP2 mandates need both fast metadata queries (Postgres) and tamper-proof raw-blob retention (object storage). Splitting them keeps the hot path indexed and the cold blobs cheap. Two curls, both real services, both encrypted at rest — exactly the shape a compliance auditor expects to see, without an AWS-Organizations setup project. ## Related cases - [AP2 mandate broker](/use-cases/ap2-mandate-broker) — the live-broker counterpart to this audit-only store - [Agent-marketplace escrow](/use-cases/agent-marketplace-escrow) — another signed-commitment ledger for agent commerce - [x402 micropayment ledger](/use-cases/x402-micropayment-ledger) — the micropayment counterpart that this mandate authorizes --- URL: /use-cases/ap2-mandate-broker.md --- --- title: AP2 mandate broker category: O. Cross-agent commerce & payments services: ["pg", "webhook"] scenario: A Google-AP2-style mandate service stores a user's shopping mandate in Postgres, lets buyer agents request approval via webhook, and emits signed receipts for each purchase. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Google-AP2-style mandate service stores a user's shopping mandate in Postgres, lets buyer agents request approval via webhook, and emits signed receipts for each purchase. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + webhook receiver) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're a Google-AP2-style mandate broker. Users register shopping mandates in Postgres. Buyer agents POST to /mandates/{id}/spend with a candidate purchase; you validate against the mandate's constraints, fire a webhook to the merchant if approved, and persist the signed receipt back to the row. Reject if the mandate is expired or over-budget. ``` ## Steps to follow - **Step 1: Provision Postgres + webhook.** ```bash PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"ap2-mandate-broker-db"}' -H "Authorization: Bearer $T" | jq -r .connection_url) HOOK=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"ap2-mandate-broker-webhook"}' -H "Authorization: Bearer $T" | jq -r .receive_url) ``` - **Step 2: Mandate + receipts schema.** ```sql CREATE TABLE mandates ( id uuid PRIMARY KEY, user_id text NOT NULL, budget_cents int NOT NULL, spent_cents int NOT NULL DEFAULT 0, expires_at timestamptz NOT NULL ); CREATE TABLE receipts ( receipt_id uuid PRIMARY KEY, mandate_id uuid REFERENCES mandates(id), amount_cents int, merchant text, signed_at timestamptz DEFAULT now() ); ``` - **Step 3: Atomic spend — only succeeds if within budget and unexpired.** ```sql UPDATE mandates SET spent_cents = spent_cents + $2 WHERE id = $1 AND spent_cents + $2 <= budget_cents AND expires_at > now() RETURNING id; ``` - **Step 4: On success, fire the webhook with a signed receipt.** ```python receipt = sign_receipt(mandate_id, amount, merchant, BROKER_KEY) requests.post(MERCHANT_WEBHOOK, json=receipt) pg.execute("INSERT INTO receipts VALUES (%s,%s,%s,%s)", (receipt["id"], mandate_id, amount, merchant)) ``` ## Why this works on instanode.dev Mandate brokers live or die on atomic budget checks — concurrent buyer agents racing to spend can't double-debit. Postgres' conditional UPDATE solves it in one statement. The webhook URL is a stable, replayable endpoint that the merchant can subscribe to, so you don't need Pub/Sub or SNS. Two curls, full AP2-shaped flow. ## Related cases - [AP2 mandate audit trail](/use-cases/ap2-mandate-audit-trail) — the archival half of this live broker - [Agent-marketplace escrow](/use-cases/agent-marketplace-escrow) — complementary commitment layer for buyer-seller flows - [Stripe-ACP checkout agent](/use-cases/stripe-acp-checkout-agent) — the Stripe-rail alternative to the AP2 spec --- URL: /use-cases/arxiv-and-rss-research-feed.md --- --- title: arXiv-and-RSS research feed category: D. Personal AI services: ["webhook", "redis", "storage"] scenario: A research agent receives webhook pings from arXiv and RSS bridges, dedupes via Redis, and stores PDFs for later retrieval. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a research agent receives webhook pings from arXiv and RSS bridges, dedupes via Redis, and stores PDFs for later retrieval. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + Redis + S3-compatible storage) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're my research agent. Subscribe to arXiv + RSS bridges via a webhook URL. On each ping, dedupe by paper_id in Redis (TTL 30 days). For new papers, download the PDF to S3-compatible storage under `papers/{arxiv_id}.pdf`. Surface unread papers when I ask. ``` ## Steps to follow - **Step 1: Provision the trio.** ```bash HOOK=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"arxiv-and-rss-research-feed-webhook"}' -H "Authorization: Bearer $T" | jq -r .receive_url) REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"arxiv-and-rss-research-feed-cache"}' -H "Authorization: Bearer $T" | jq -r .connection_url) curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"arxiv-and-rss-research-feed-storage"}' -H "Authorization: Bearer $T" > s3.json ``` - **Step 2: Register the webhook with your RSS bridge service.** Point arXiv-RSS-bridge (or similar) at `$HOOK`. - **Step 3: Poll the webhook inbox, dedupe, fetch PDF.** ```python pings = requests.get(f"https://api.instanode.dev/api/v1/webhooks/{TOKEN}/requests").json() for p in pings: paper = p["body"] if r.set(f"seen:{paper['id']}", "1", nx=True, ex=86400*30): pdf = requests.get(paper["pdf_url"]).content s3.put_object(Bucket="instant-shared", Key=f"papers/{paper['id']}.pdf", Body=pdf) r.lpush("queue:unread", paper["id"]) ``` - **Step 4: Surface unread on demand.** ```python unread = [r.lpop("queue:unread") for _ in range(10) if r.llen("queue:unread")] ``` ## Why this works on instanode.dev Personal-research agents shouldn't need a server. A webhook URL is the inbox, Redis SET-NX is the dedupe primitive, S3-compatible storage is the PDF archive — three curls, no Lambda, no DynamoDB GSI. The webhook receive endpoint is queryable via HTTP so the agent can pull on its own cadence instead of running a 24/7 listener. ## Related cases - [Obsidian-vault embedding sync](/use-cases/obsidian-vault-embedding-sync) — downstream sink that indexes the papers this feed pulls in - [Voice-memo capture pipeline](/use-cases/voice-memo-capture-pipeline) — another personal-AI ingestion pipeline with audio instead of papers - [Overnight dossier fleet](/use-cases/overnight-dossier-fleet) — consumes the same kind of feed to generate scheduled briefings --- URL: /use-cases/autogen-group-chat-history.md --- --- title: AutoGen group-chat history category: B. Multi-agent systems services: ["mongo"] scenario: An AutoGen multi-agent chat stores per-conversation message logs in Mongo for audit and replay across days. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an AutoGen multi-agent chat stores per-conversation message logs in Mongo for audit and replay across days. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (MongoDB) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're running an AutoGen GroupChat with 5 agents (Planner, Coder, Critic, Tester, Summarizer). Persist every message — speaker, content, timestamp, turn_id — to MongoDB so we can replay conversations weeks later and audit which agent said what. Index on (conversation_id, turn_id). ``` ## Steps to follow - **Step 1: Provision Mongo.** ```bash MONGO=$(curl -sX POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"autogen-group-chat-history-mongo"}' \ -H "Authorization: Bearer $T" | jq -r .connection_url) ``` - **Step 2: Index the access pattern.** ```python from pymongo import MongoClient, ASCENDING col = MongoClient(MONGO).autogen.messages col.create_index([("conversation_id", ASCENDING), ("turn_id", ASCENDING)], unique=True) col.create_index([("speaker", ASCENDING), ("ts", ASCENDING)]) ``` - **Step 3: AutoGen message hook — write every speaker turn.** ```python def on_message(speaker, content, conv_id, turn_id): col.insert_one({ "conversation_id": conv_id, "turn_id": turn_id, "speaker": speaker.name, "content": content, "ts": datetime.utcnow(), }) group_chat.register_reply([Agent, None], reply_func=on_message) ``` - **Step 4: Replay a conversation in order.** ```python for m in col.find({"conversation_id": cid}).sort("turn_id", 1): print(f"[{m['speaker']}] {m['content']}") ``` ## Why this works on instanode.dev AutoGen messages have variable shape — function_call payloads, code blocks, multi-modal content — and a rigid SQL schema fights you. Mongo's flexible documents map 1:1 to the runtime objects. One curl gives you a real Mongo with real indexes (not in-memory mock), and the same DB scales from a single GroupChat replay to thousands of audit-worthy conversations. ## Related cases - [LangGraph state checkpoints](/use-cases/langgraph-state-checkpoints) — the framework-native checkpointing alternative in Postgres - [Cross-device chat history](/use-cases/cross-device-chat-history) — the same Mongo conversation log scoped to a single user - [Conversation transcript archive](/use-cases/conversation-transcript-archive) — another append-only archive of agent dialogue, just S3-flavored --- URL: /use-cases/browser-agent-action-pool.md --- --- title: Browser-agent action pool category: M. Parallel tool execution services: ["mongo", "nats"] scenario: A Skyvern-style planner emits 20 actions (fill, click, scroll) that fan out across 20 Browserbase tabs simultaneously; results aggregate in Mongo keyed by step_id. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Skyvern-style planner emits 20 actions (fill, click, scroll) that fan out across 20 Browserbase tabs simultaneously; results aggregate in Mongo keyed by step_id. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (MongoDB + NATS JetStream) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're a Skyvern-style planner. After analyzing a target page, you emit 20 actions (fill, click, scroll, extract). Fan them out across 20 Browserbase tabs via NATS subjects, each tab posts its result to Mongo keyed by step_id. The planner aggregates results and moves to the next plan step. Don't wait sequentially. ``` ## Steps to follow - **Step 1: Provision the queue + result store.** ```bash NATS=$(curl -sX POST https://api.instanode.dev/queue/new -H 'Content-Type: application/json' -d '{"name":"browser-agent-action-pool-queue"}' -H "Authorization: Bearer $T" | jq -r .connection_url) MONGO=$(curl -sX POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"browser-agent-action-pool-mongo"}' -H "Authorization: Bearer $T" | jq -r .connection_url) ``` - **Step 2: Planner publishes 20 actions, one subject per action type.** ```python for step in plan.steps: await nc.publish(f"browser.{step.action}", json.dumps({"step_id": step.id, "selector": step.selector, "value": step.value, "tab_hint": step.tab}).encode()) ``` - **Step 3: Browser worker — pull, act, persist.** ```python async def worker(sub_name): async for msg in nc.subscribe(f"browser.{sub_name}"): s = json.loads(msg.data) tab = await browserbase.session_for(s["tab_hint"]) out = await execute(tab, s["selector"], s["value"]) col.insert_one({"step_id": s["step_id"], "result": out, "completed_at": datetime.utcnow()}) ``` - **Step 4: Planner polls Mongo for completion of the batch.** ```python expected = set(s.id for s in plan.steps) while True: done = {d["step_id"] for d in col.find({"step_id": {"$in": list(expected)}})} if expected.issubset(done): break await asyncio.sleep(0.1) ``` ## Why this works on instanode.dev 20 browser tabs in parallel is the hard part; the easy parts shouldn't slow you down. NATS subjects route actions to worker pools without an in-process scheduler; Mongo's keyed write is idempotent on step_id. Two curls and the data-plane disappears as a concern, leaving you to focus on the actual hard problem of recovering when a tab hits a CAPTCHA. ## Related cases - [Accessibility-tree selector cache](/use-cases/accessibility-tree-selector-cache) — the selector-resolution layer underneath these parallel actions - [Anthropic parallel tool_use batch](/use-cases/anthropic-parallel-tool-use-batch) — the same fan-out idea applied to model tool_use blocks - [Browser job queue with retries](/use-cases/browser-job-queue-with-retries) — single-worker queue equivalent for navigation tasks --- URL: /use-cases/browser-job-queue-with-retries.md --- --- title: Browser job queue with retries category: E. Browser & automation agents services: ["nats"] scenario: A fleet of Playwright workers pulls navigation tasks from a queue, marks them done, and retries on captcha. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a fleet of Playwright workers pulls navigation tasks from a queue, marks them done, and retries on captcha. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're running a fleet of 30 Playwright workers. Pull navigation jobs (url, action, retry_count) from a NATS work-queue. On success, ack. On CAPTCHA detection, requeue with retry_count++ and a 30s delay. After 3 retries, route to the dead-letter subject for human review. ``` ## Steps to follow - **Step 1: Provision NATS JetStream queue.** ```bash curl -sX POST https://api.instanode.dev/queue/new -H 'Content-Type: application/json' -d '{"name":"browser-job-queue-with-retries-queue"}' \ -H "Authorization: Bearer $T" | jq . # response contains connection_url with creds and a JetStream stream name ``` - **Step 2: Create the work stream + DLQ subject.** ```python import nats nc = await nats.connect(NATS_URL) js = nc.jetstream() await js.add_stream(name="browser_jobs", subjects=["jobs.navigate","jobs.dlq"], retention="workqueue") ``` - **Step 3: Worker — pull, run, ack or requeue.** ```python sub = await js.pull_subscribe("jobs.navigate", durable="worker-fleet") while True: msgs = await sub.fetch(1, timeout=5) for m in msgs: job = json.loads(m.data) try: await playwright_run(job["url"], job["action"]) await m.ack() except CaptchaDetected: job["retry_count"] += 1 subject = "jobs.dlq" if job["retry_count"] >= 3 else "jobs.navigate" await js.publish(subject, json.dumps(job).encode()) await m.ack() ``` - **Step 4: Drain the DLQ periodically.** ```bash nats stream view browser_jobs --subjects=jobs.dlq ``` ## Why this works on instanode.dev JetStream gives you real durable queues with per-consumer cursors — exactly-once-ish semantics for browser jobs that take 30s each. Compared to SQS, no visibility-timeout tuning hell; compared to Sidekiq, no Redis-cluster setup. One curl, one stream, 30 workers pulling concurrently with zero coordination code. ## Related cases - [Durable agent task queue](/use-cases/durable-agent-task-queue) — the same NATS-with-backoff pattern at the supervisor level - [Browser-agent action pool](/use-cases/browser-agent-action-pool) — fans these queued jobs out across parallel tabs - [Cron-scheduled scraping swarm](/use-cases/cron-scheduled-scraping-swarm) — scheduled producer for the kind of jobs this queue runs --- URL: /use-cases/browser-session-cookie-store.md --- --- title: Browser-session cookie store category: E. Browser & automation agents services: ["redis"] scenario: A browser agent persists login cookies and session state per target site so it doesn't re-auth on every run. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a browser agent persists login cookies and session state per target site so it doesn't re-auth on every run. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're a browser agent that targets 8 different sites. Each site needs its own logged-in session. Persist cookies per site in Redis as a hash (key: `session:{site}`, fields: cookie name to value). Before each run, hydrate the browser context from Redis. After login or refresh, write the new cookie set back. ``` ## Steps to follow - **Step 1: Provision Redis.** ```bash REDIS_URL=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"browser-session-cookie-store-cache"}' \ -H "Authorization: Bearer $T" | jq -r .connection_url) ``` - **Step 2: Hydrate the Playwright context from Redis.** ```python import redis, json from playwright.sync_api import sync_playwright r = redis.from_url(REDIS_URL) def load_cookies(site): raw = r.get(f"session:{site}") return json.loads(raw) if raw else [] ctx = browser.new_context() ctx.add_cookies(load_cookies("linkedin")) ``` - **Step 3: Persist after every successful action.** ```python def save_cookies(site, ctx): cookies = ctx.cookies() r.set(f"session:{site}", json.dumps(cookies), ex=86400*7) ``` - **Step 4: Refresh-on-expiry workflow.** ```python page = ctx.new_page() page.goto("https://linkedin.com/feed") if "login" in page.url: run_login_flow(page) save_cookies("linkedin", ctx) ``` ## Why this works on instanode.dev Cookie state is small (~10KB per site), hot (read at every run start), and ephemeral (7-day TTL is a feature, not a bug). Redis is the right shape, but spinning up ElastiCache for this is overkill. One curl, real Redis, EXPIRE built-in. Across 8 sites you avoid 8 re-auth flows per agent run — that's minutes saved per session. ## Related cases - [Accessibility-tree selector cache](/use-cases/accessibility-tree-selector-cache) — complementary Redis cache that speeds up the same browser agent - [Form-fill state machine](/use-cases/form-fill-state-machine) — auth state these cookies provide is what lets form-fill resume - [Per-agent rate-limited API key vault](/use-cases/per-agent-rate-limited-api-key-vault) — another secrets-in-Redis pattern with scoped access --- URL: /use-cases/ci-flake-tracker.md --- --- title: CI flake-tracker category: F. Developer tooling services: ["webhook", "pg"] scenario: A CI bot ingests test-run webhooks, fingerprints failures, and surfaces "this test is flaky 30% of runs". --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a CI bot ingests test-run webhooks, fingerprints failures, and surfaces "this test is flaky 30% of runs". Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're a CI flakiness tracker. Receive GitHub Actions / CircleCI webhooks on every test run. Fingerprint failures by (test_name + sha256(stack_trace_first_line)). Store run history in Postgres. Compute "flaky" as "passed in some runs, failed in others within the last 7 days" and surface a daily list. ``` ## Steps to follow - **Step 1: Provision webhook + Postgres.** ```bash HOOK=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"ci-flake-tracker-webhook"}' -H "Authorization: Bearer $T" | jq -r .receive_url) PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"ci-flake-tracker-db"}' -H "Authorization: Bearer $T" | jq -r .connection_url) ``` - **Step 2: Configure CI to POST results to `$HOOK`.** ```yaml # .github/workflows/test.yml - name: Report results if: always() run: | curl -X POST "$WEBHOOK" -H 'content-type: application/json' \ -d "$(jq -n --arg sha "$GITHUB_SHA" --slurpfile r results.json \ '{sha:$sha, tests:$r[0]}')" ``` - **Step 3: Schema with fingerprint.** ```sql CREATE TABLE test_runs ( id bigserial PRIMARY KEY, commit_sha text NOT NULL, test_name text NOT NULL, fingerprint text, status text CHECK (status IN ('pass','fail','skip')), ran_at timestamptz DEFAULT now() ); CREATE INDEX idx_test_recent ON test_runs (test_name, ran_at DESC); ``` - **Step 4: Flake query — pass-AND-fail within 7d.** ```sql SELECT test_name, COUNT(*) FILTER (WHERE status='fail')::float / COUNT(*) AS fail_rate, COUNT(*) AS n FROM test_runs WHERE ran_at > now() - interval '7 days' GROUP BY test_name HAVING COUNT(DISTINCT status) > 1 AND COUNT(*) > 10 ORDER BY fail_rate DESC LIMIT 20; ``` ## Why this works on instanode.dev Flake tracking is two pieces: an HTTP sink for CI to POST to, and SQL to compute pass/fail variance. The webhook URL is already a public endpoint with stored history — your CI doesn't need to know about your DB. The SQL is bog-standard but needs real indexes (the HAVING DISTINCT trick is slow on a non-indexed test_name column). Two curls, no Datadog bill. ## Related cases - [SARIF scan-result store](/use-cases/sarif-scan-result-store) — another CI-side Postgres warehouse for tracking drift over time - [PR-review bot triggered by webhooks](/use-cases/pr-review-bot-triggered-by-webhooks) — consumes the same kind of GitHub webhook firehose - [High-volume PR-review pipeline](/use-cases/high-volume-pr-review-pipeline) — the at-scale version of the same CI-feedback loop --- URL: /use-cases/classroom-per-student-sandbox.md --- --- title: Classroom-per-student sandbox category: I. Hackathon & education services: ["pg"] scenario: A CS professor provisions one ephemeral Postgres per student for a SQL assignment, dropped after grading. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a CS professor provisions one ephemeral Postgres per student for a SQL assignment, dropped after grading. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're a CS professor running a SQL assignment for 40 students. Provision one ephemeral Postgres per student, seed it with the assignment fixture data, hand out connection URLs. After grading on Friday, let them expire — no manual teardown. ``` ## Steps to follow - **Step 1: Loop the roster, provision per student.** ```bash while read student email; do url=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"classroom-per-student-sandbox-db"}' | jq -r .connection_url) echo "$student,$email,$url" >> handouts.csv done < roster.csv ``` - **Step 2: Seed each DB with the assignment fixture.** ```bash while IFS=, read student email url; do psql "$url" -f assignment_seed.sql & done < handouts.csv wait ``` - **Step 3: Email each student their personal URL.** The assignment uses standard SQL — they connect from psql, DataGrip, anything. ```python for row in csv.DictReader(open("handouts.csv")): send_mail(row["email"], subject="CS 348 Assignment 3 — your DB", body=f"psql {row['url']}\n\nWork through problems 1-10.") ``` - **Step 4: After grading, do nothing.** Anonymous resources auto-expire at T+24h; for a 7-day variant use claimed tokens with a manual delete after grading. ```bash # Optional explicit teardown: curl -X DELETE "https://api.instanode.dev/api/v1/resources/$id" \ -H "Authorization: Bearer $TEACHER_TOKEN" ``` ## Why this works on instanode.dev 40 fresh Postgres instances for one assignment is comically expensive on RDS and operationally annoying on shared schemas (students nuke each other's tables). Per-student isolated databases via one curl each — total provisioning cost: zero, total teardown cost: zero. Students can also `DROP DATABASE` in their own without affecting peers. ## Related cases - [24-hour hackathon backend](/use-cases/24-hour-hackathon-backend) — another education-flavored ephemeral provisioning pattern - [Ephemeral test database for a risky migration](/use-cases/ephemeral-test-database-for-a-risky-migration) — the per-task version of the same throwaway-Postgres pattern - [Adaptive-tutoring student model](/use-cases/adaptive-tutoring-student-model) — pairs naturally as the tutoring layer over per-student sandboxes --- URL: /use-cases/claude-code-agent-teams-scratchpad.md --- --- title: Claude Code agent-teams scratchpad category: J. Agent swarms & fan-out services: ["pg", "redis"] scenario: A lead Claude Code session spawns 6 sibling worker sessions, each owning one module of a monorepo; they coordinate by reading and writing a shared scratchpad table. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a lead Claude Code session spawns 6 sibling worker sessions, each owning one module of a monorepo; they coordinate by reading and writing a shared scratchpad table. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're the lead Claude Code session orchestrating 6 worker sessions, each owning one module of a monorepo (auth, billing, search, web, mobile, infra). They coordinate by writing status updates to a shared scratchpad table in Postgres and a "currently editing" lock in Redis. Before touching a file, a worker SET-NX-locks it. ``` ## Steps to follow - **Step 1: Provision the coordination plane.** ```bash PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"claude-code-agent-teams-scratchpad-db"}' -H "Authorization: Bearer $T" | jq -r .connection_url) REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"claude-code-agent-teams-scratchpad-cache"}' -H "Authorization: Bearer $T" | jq -r .connection_url) ``` - **Step 2: Scratchpad table — every session appends, all read.** ```sql CREATE TABLE scratchpad ( id bigserial PRIMARY KEY, session text NOT NULL, module text NOT NULL, note text NOT NULL, posted_at timestamptz DEFAULT now() ); CREATE INDEX idx_recent ON scratchpad (posted_at DESC); ``` - **Step 3: File lock before editing — Redis SET NX EX.** ```python def claim_file(path, session, ttl=600): ok = r.set(f"lock:{path}", session, nx=True, ex=ttl) return bool(ok) if not claim_file("api/internal/handlers/billing.go", "worker-3"): raise RuntimeError("file held by another session") ``` - **Step 4: Post a status update so the lead can survey progress.** ```sql INSERT INTO scratchpad (session, module, note) VALUES ('worker-3', 'billing', 'refactored razorpay webhook handler, tests green'); ``` - **Step 5: Lead's dashboard query.** ```sql SELECT DISTINCT ON (session) session, module, note, posted_at FROM scratchpad ORDER BY session, posted_at DESC; ``` ## Why this works on instanode.dev Multi-agent Claude Code sessions need cheap shared state without standing up a service. Postgres for ordered durable notes, Redis for sub-second file locks — the two primitives that solve "who's editing what" cleanly. Two curls, both real, both visible from any of the 6 worker shells via psql/redis-cli for live debugging. ## Related cases - [Multi-repo shared scratchpad](/use-cases/multi-repo-shared-scratchpad) — the Mongo-document version of the same shared-coordination idea - [Coding-agent cross-session memory](/use-cases/coding-agent-cross-session-memory) — longer-horizon memory that survives across sessions, not just teams - [Shared episodic memory store](/use-cases/shared-episodic-memory-store) — generalizes the scratchpad table beyond coding agents --- URL: /use-cases/clinical-scribe-note-storage.md --- --- title: Clinical-scribe note storage category: C. Vertical AI apps services: ["pg", "storage"] scenario: A medical scribe agent transcribes doctor-patient visits and stores structured SOAP notes per encounter with auditable history. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a medical scribe agent transcribes doctor-patient visits and stores structured SOAP notes per encounter with auditable history. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + S3-compatible storage) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're a clinical-scribe agent transcribing doctor-patient visits. For each visit, store structured SOAP fields (Subjective, Objective, Assessment, Plan) in Postgres for queryability, and the raw audio + full transcript blob in S3-compatible storage for audit. Every edit creates a new version row — never overwrite. ``` ## Steps to follow - **Step 1: Provision PG + bucket.** ```bash PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"clinical-scribe-note-storage-db"}' -H "Authorization: Bearer $T" | jq -r .connection_url) curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"clinical-scribe-note-storage-storage"}' -H "Authorization: Bearer $T" > s3.json ``` - **Step 2: Versioned SOAP table.** ```sql CREATE TABLE soap_notes ( note_id uuid NOT NULL, version int NOT NULL, encounter_id uuid NOT NULL, subjective text, objective text, assessment text, plan text, audio_key text, transcript_key text, authored_by text NOT NULL, authored_at timestamptz DEFAULT now(), PRIMARY KEY (note_id, version) ); CREATE INDEX idx_encounter ON soap_notes (encounter_id, version DESC); ``` - **Step 3: Upload raw audio + transcript, insert metadata.** ```python audio_key = f"audio/{encounter_id}.opus" tx_key = f"transcripts/{encounter_id}.json" s3.put_object(Bucket="instant-shared", Key=audio_key, Body=audio_bytes) s3.put_object(Bucket="instant-shared", Key=tx_key, Body=json.dumps(transcript)) pg.execute("""INSERT INTO soap_notes (note_id,version,encounter_id, subjective,objective,assessment,plan,audio_key,transcript_key,authored_by) VALUES (%s,1,%s,%s,%s,%s,%s,%s,%s,%s)""", (nid, encounter_id, S, O, A, P, audio_key, tx_key, "scribe-v3")) ``` - **Step 4: Latest version of a note.** ```sql SELECT * FROM soap_notes WHERE note_id = $1 ORDER BY version DESC LIMIT 1; ``` ## Why this works on instanode.dev Clinical data needs strict auditability — every edit visible, raw artifacts untouched. Versioned PG rows + immutable objects in S3-compatible storage give that without a custom CDC pipeline. Both resources encrypt at rest by default. Two curls; the same setup that's HIPAA-shaped on day one scales without a re-platform when you go from one clinic pilot to a real deployment. ## Related cases - [Personal-injury demand letters](/use-cases/personal-injury-demand-letters) — another vertical-AI workflow with auditable versioned documents - [Voice-memo capture pipeline](/use-cases/voice-memo-capture-pipeline) — the audio-capture front end that feeds into structured notes - [EHR appointment webhook fan-in](/use-cases/ehr-appointment-webhook-fan-in) — the upstream event source that triggers a scribe session --- URL: /use-cases/cloudflare-sub-agent-factory-per-user.md --- --- title: Cloudflare sub-agent factory per user category: L. Agent-factory / spawning patterns services: ["pg", "deploy"] scenario: A Durable-Object-style root agent mints a fresh sub-agent for each end-user, each with its own SQL-backed memory and a deploy slot for that user's tools. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Durable-Object-style root agent mints a fresh sub-agent for each end-user, each with its own SQL-backed memory and a deploy slot for that user's tools. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You operate a Cloudflare-Durable-Object-style sub-agent factory. When an end-user first interacts, mint them a fresh sub-agent: a row in agents Postgres, an isolated database for that agent's memory, and a deploy slot hosting that user's tool-runner. Resolve subsequent requests by user_id to the same sub-agent. ``` ## Steps to follow - **Step 1: Provision the control-plane Postgres.** ```bash PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"cloudflare-sub-agent-factory-per-u-db"}' -H "Authorization: Bearer $T" | jq -r .connection_url) ``` - **Step 2: Agent registry schema.** ```sql CREATE TABLE sub_agents ( user_id text PRIMARY KEY, agent_db_url text NOT NULL, deploy_url text NOT NULL, spawned_at timestamptz DEFAULT now(), last_active_at timestamptz ); ``` - **Step 3: On first request, mint memory DB + tool-runner deploy.** ```python def get_or_spawn(user_id): row = pg.fetchone("SELECT agent_db_url, deploy_url FROM sub_agents WHERE user_id=%s", (user_id,)) if row: return row mem = requests.post("https://api.instanode.dev/db/new", headers={"Authorization": f"Bearer {T}"}).json() dep = requests.post("https://api.instanode.dev/deploy/new", headers={"Authorization": f"Bearer {T}"}, json={"image": "ghcr.io/me/tool-runner:latest", "env": {"DATABASE_URL": mem["connection_url"], "USER_ID": user_id}}).json() pg.execute("INSERT INTO sub_agents VALUES (%s,%s,%s,now(),now())", (user_id, mem["connection_url"], dep["app_url"])) return mem["connection_url"], dep["app_url"] ``` - **Step 4: Route the user's request to their sub-agent.** ```python db_url, deploy_url = get_or_spawn(user_id) requests.post(f"{deploy_url}/handle", json=request_payload) ``` ## Why this works on instanode.dev Per-user isolation done right needs per-user resources, not per-user schemas inside one giant DB. `POST /db/new` + `POST /deploy/new` per first-time user gives the same isolation guarantee Durable Objects provide, without writing a Workers-runtime port. The control-plane Postgres maps user_id to (db, deploy) in one row; subsequent requests skip provisioning entirely. Cold-start spawn is two curls, ~2 seconds. ## Related cases - [AgentCore tenant-scoped spawning](/use-cases/agentcore-tenant-scoped-spawning) — tenant-org-scoped variant of the same factory pattern - [Per-tenant chatbot factory at signup](/use-cases/per-tenant-chatbot-factory-at-signup) — B2B SaaS sibling that adds Mongo+Redis per tenant - [Smithery one-MCP-per-skill mint](/use-cases/smithery-one-mcp-per-skill-mint) — factory variant that mints one runtime per skill, not per user --- URL: /use-cases/coding-agent-cross-session-memory.md --- --- title: Coding-agent cross-session memory category: A. AI coding agents services: ["pg"] scenario: A terminal-resident coding agent persists architectural decisions across days so it can recall "what we tried Tuesday" via pgvector similarity search. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a terminal-resident coding agent persists architectural decisions across days so it can recall "what we tried Tuesday" via pgvector similarity search. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're my terminal coding agent across a multi-week refactor of our billing service. Last Tuesday we tried wrapping Stripe webhooks in an idempotency table; on Thursday we tried a Redis lock; today I want to compare and pick one. Claim a Postgres on instanode.dev for our long-term decision log (or recover it if a JWT is already in ~/.config/instanode/token), enable pgvector, ensure a `decisions` table exists with topic + body + embedding + tags, and at the end of every session write a row for each major architectural choice we made. When I ask "what did we try about webhooks?" embed the query with text-embedding-3-small and return the top 3 cosine-nearest decisions with their dates. ``` ## Steps to follow We'll thread one running log — the multi-week refactor of a billing service — through every step. By the last command you'll watch the agent recall a decision made nine days ago by similarity, not by keyword. - **Step 1: Claim a Postgres once, cache the JWT, recover it on every subsequent run.** Cross-session means the URL has to survive `Ctrl-D`. The agent caches the claimed token in `~/.config/instanode/token` so the next session resumes the same database. ```bash TOKEN_FILE=~/.config/instanode/token if [ -f "$TOKEN_FILE" ]; then PG_URL=$(curl -s -H "Authorization: Bearer $(cat $TOKEN_FILE)" \ https://api.instanode.dev/api/v1/resources | jq -r '.[] | select(.type=="postgres") | .connection_url') else mkdir -p ~/.config/instanode RESP=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"coding-agent-cross-session-memory-db"}') echo "$RESP" | jq -r .token > "$TOKEN_FILE" PG_URL=$(echo "$RESP" | jq -r .connection_url) # then visit the printed claim_url within 24h to upgrade from anonymous → hobby echo "claim within 24h: $(echo $RESP | jq -r .claim_url)" fi export PG_URL ``` - **Step 2: Enable pgvector and create the schema once.** instanode ships pgvector pre-installed on every provisioned Postgres — no `CREATE EXTENSION` failure on permissions. ```sql CREATE EXTENSION IF NOT EXISTS vector; CREATE TABLE IF NOT EXISTS decisions ( id bigserial PRIMARY KEY, decided_at timestamptz NOT NULL DEFAULT now(), session_id text NOT NULL, topic text NOT NULL, body text NOT NULL, tags text[] NOT NULL DEFAULT '{}', embedding vector(1536) NOT NULL ); CREATE INDEX IF NOT EXISTS decisions_topic_idx ON decisions USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100); ``` - **Step 3: At session end, the agent logs each architectural choice.** Embed → insert. Same code path every time, no manual journaling. ```python # agent/log_decision.py import os, openai, psycopg oa = openai.OpenAI() def log(session_id: str, topic: str, body: str, tags: list[str]) -> int: emb = oa.embeddings.create( model="text-embedding-3-small", input=f"{topic}\n\n{body}", dimensions=1536, ).data[0].embedding with psycopg.connect(os.environ["PG_URL"]) as cn: row = cn.execute( "INSERT INTO decisions (session_id, topic, body, tags, embedding) " "VALUES (%s, %s, %s, %s, %s) RETURNING id", (session_id, topic, body, tags, emb), ).fetchone() return row[0] # called by the agent at the end of Tuesday's session: log("2026-04-21", "Stripe webhook idempotency", "Tried a Postgres idempotency table keyed on stripe_event_id. " "Insert ON CONFLICT DO NOTHING; if rowcount=0, short-circuit. " "Concern: table growth — needs a TTL job.", ["stripe", "idempotency", "webhooks"]) ``` - **Step 4: Recall by meaning, not keyword.** When you ask "what did we try about webhooks?" the agent embeds the question and runs a cosine search. Note that "webhook" never appears verbatim in Thursday's Redis-lock body — but the embedding still pulls it. ```python def recall(question: str, k: int = 3): qe = oa.embeddings.create( model="text-embedding-3-small", input=question, dimensions=1536 ).data[0].embedding with psycopg.connect(os.environ["PG_URL"]) as cn: return cn.execute( "SELECT decided_at::date, topic, body, " " 1 - (embedding <=> %s::vector) AS similarity " "FROM decisions " "ORDER BY embedding <=> %s::vector LIMIT %s", (qe, qe, k), ).fetchall() for d, topic, body, sim in recall("what did we try about webhooks?"): print(f"[{d}] ({sim:.3f}) {topic}\n {body[:120]}...\n") ``` - **Step 5: Verify recall works across sessions.** Open a fresh terminal — no warm cache, no in-process state — and run the recall. ```bash # fresh shell, no agent state: python -c "from agent.log_decision import recall; \ [print(r[0], '|', r[1], '|', round(r[3],3)) for r in recall('webhook deduplication', 3)]" # 2026-04-21 | Stripe webhook idempotency | 0.872 # 2026-04-23 | Redis SETNX lock for inbound webhooks | 0.841 # 2026-04-15 | Outbound retry backoff | 0.612 ``` ## Why this works on instanode.dev Long-running agent memory has been awkwardly served by two opposite camps. The **Pinecone / Weaviate / Qdrant Cloud** path is a real vector DB but assumes a signup, a project, an API key, and a paid tier the moment you cross the free quota — and worse, an agent that wants to *spawn* its own memory store can't, because Pinecone's project creation isn't an open POST. The **LangChain InMemoryVectorStore** / **Chroma-on-disk** path solves provisioning by being local, but the data dies when the laptop sleeps or when a sibling agent on another machine wants to read it. **OpenAI Assistants memory** locks you into one provider's storage. instanode gives the agent a real Postgres with pgvector pre-installed in one unauthenticated POST — no extension-install dance (a common pgvector failure mode on shared Postgres providers like Supabase free), no project quota, no IAM. The claimed token survives terminal restarts, IDE reloads, machine reboots, and any other device the agent runs on, because the JWT itself is the recovery key. The same `decisions` table is queryable from a Python script, a `psql` shell, or another agent — because it's just Postgres. ## Related cases - [Claude Code agent-teams scratchpad](/use-cases/claude-code-agent-teams-scratchpad) — the across-siblings counterpart to across-sessions memory - [Multi-repo shared scratchpad](/use-cases/multi-repo-shared-scratchpad) — scratchpad that spans repos instead of time - [Obsidian-vault embedding sync](/use-cases/obsidian-vault-embedding-sync) — same pgvector recall pattern over personal notes --- URL: /use-cases/contract-redline-cache.md --- --- title: Contract redline cache category: C. Vertical AI apps services: ["pg", "redis"] scenario: A contract-review agent caches clause embeddings so re-running redlines on a 200-page MSA is instant on the second pass. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a contract-review agent caches clause embeddings so re-running redlines on a 200-page MSA is instant on the second pass. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're reviewing a 200-page MSA. Claim Postgres + Redis on instanode.dev. Chunk the MSA into clauses, embed each one, store in Postgres with pgvector, and cache clause-hash → redline-output in Redis. On re-run, before calling the LLM for a clause, check Redis first. ``` ## Steps to follow - **Step 1: Provision storage and cache.** Two curls; both return connection URLs in under a second. ```bash PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"contract-redline-cache-db"}' | jq -r .connection_url) REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"contract-redline-cache-cache"}' | jq -r .connection_url) ``` - **Step 2: Set up the clause table.** Hash + embedding indexed for fast similarity lookup. ```sql CREATE EXTENSION IF NOT EXISTS vector; CREATE TABLE clauses ( id bigserial PRIMARY KEY, clause_hash bytea UNIQUE, text text, embedding vector(1536) ); ``` - **Step 3: Cache-check before LLM call.** Hash the clause and probe Redis. ```python h = hashlib.sha256(clause.encode()).hexdigest() cached = r.get(f"redline:{h}") if cached: return json.loads(cached) redline = llm.redline(clause) r.setex(f"redline:{h}", 86400, json.dumps(redline)) ``` - **Step 4: Persist embeddings for the next MSA.** Future contracts reuse known-good redlines via similarity. ```sql INSERT INTO clauses (clause_hash, text, embedding) VALUES ($1, $2, $3) ON CONFLICT (clause_hash) DO NOTHING; ``` ## Why this works on instanode.dev Same-token provisioning means Postgres and Redis share the same anonymous JWT — no two-service signup, no IAM. Both URLs are AES-256 encrypted at rest. The second pass over the same MSA hits Redis 100% of the time and skips $40 of GPT-4 calls. When the deal closes, claim the token and the resources upgrade to a permanent hobby plan without re-provisioning. ## Related cases - [Accessibility-tree selector cache](/use-cases/accessibility-tree-selector-cache) — another Redis-fronted embedding/snapshot cache for fast re-runs - [Tool-call rate-limit and budget cache](/use-cases/tool-call-rate-limit-and-budget-cache) — Redis cache that protects the token budget those redlines burn - [Personal-injury demand letters](/use-cases/personal-injury-demand-letters) — adjacent legal-AI workflow that benefits from clause caching --- URL: /use-cases/conversation-transcript-archive.md --- --- title: Conversation transcript archive category: A. AI coding agents services: ["storage"] scenario: Coding sessions are persisted as JSONL transcripts for replay, fine-tuning, and "what did we try last sprint" search across the team. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: coding sessions are persisted as JSONL transcripts for replay, fine-tuning, and "what did we try last sprint" search across the team. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (S3-compatible storage) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Persist every coding session as a JSONL transcript to S3-compatible storage on instanode.dev. One object per session, keyed by date + agent ID. On a "what did we try last sprint" query, list objects in the last 14 days, stream them, and grep for the topic. ``` ## Steps to follow - **Step 1: Claim S3-compatible storage.** Returns a bucket URL + IAM access key scoped to this token. ```bash curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"conversation-transcript-archive-storage"}' | tee s3.json export AWS_ACCESS_KEY_ID=$(jq -r .access_key s3.json) export AWS_SECRET_ACCESS_KEY=$(jq -r .secret_key s3.json) export AWS_ENDPOINT_URL=$(jq -r .endpoint s3.json) export BUCKET=$(jq -r .bucket s3.json) ``` - **Step 2: At session end, upload the JSONL.** One object per session, partitioned by date. ```bash KEY="transcripts/$(date +%Y-%m-%d)/agent-${AGENT_ID}-$(date +%s).jsonl" aws s3 cp session.jsonl s3://$BUCKET/$KEY --endpoint-url $AWS_ENDPOINT_URL ``` - **Step 3: List recent sessions.** Standard S3 list — works with boto3, aws-cli, anything. ```python s3 = boto3.client("s3", endpoint_url=os.environ["AWS_ENDPOINT_URL"]) resp = s3.list_objects_v2(Bucket=bucket, Prefix=f"transcripts/{since}/") ``` - **Step 4: Grep across the archive.** Stream + filter without downloading. ```bash aws s3 cp s3://$BUCKET/$KEY - --endpoint-url $AWS_ENDPOINT_URL | jq 'select(.content | contains("auth refactor"))' ``` ## Why this works on instanode.dev S3-compatible storage speaks the S3 API verbatim — every existing tool (aws-cli, boto3, rclone, duckdb httpfs) works unchanged. You get a real bucket with a real IAM user scoped to your token, not a stub. No AWS account, no IAM policy authoring, no bucket-name uniqueness collision; the bucket is provisioned and ready in ~600ms. ## Related cases - [AutoGen group-chat history](/use-cases/autogen-group-chat-history) — the Mongo-backed online-replay alternative to JSONL archives - [Cross-device chat history](/use-cases/cross-device-chat-history) — live-state version of the same transcript record - [Cross-agent replay debugger](/use-cases/cross-agent-replay-debugger) — indexes transcripts like these for deterministic branch replay --- URL: /use-cases/copy-on-write-postgres-for-agent-migrations.md --- --- title: Copy-on-write Postgres for agent migrations category: K. Ephemeral agent runtimes services: ["pg"] scenario: An Ardent-style coding agent forks a 6-second copy-on-write clone of prod Postgres, runs the candidate ALTER TABLE, validates row counts, then destroys the clone. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an Ardent-style coding agent forks a 6-second copy-on-write clone of prod Postgres, runs the candidate ALTER TABLE, validates row counts, then destroys the clone. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're an Ardent-style migration agent. Take a snapshot of prod Postgres, fork a copy-on-write clone via instanode.dev, run the candidate ALTER TABLE on the clone, compare row counts and constraints against the source, and if all checks pass print the migration SQL. Destroy the clone when done. ``` ## Steps to follow - **Step 1: Provision a scratch Postgres clone.** The fork is a fresh shared Postgres seeded from a dump. ```bash CLONE_URL=$(curl -sX POST https://api.instanode.dev/db/new \ -H "Content-Type: application/json" \ -d '{"name":"copy-on-write-postgres-for-agent-m-db","seed_dump_url":"https://my-bucket.s3.amazonaws.com/prod-snapshot.sql.gz"}' \ | jq -r .connection_url) ``` - **Step 2: Run the candidate migration on the clone.** Wrap in a transaction for easy rollback while inspecting. ```sql BEGIN; ALTER TABLE orders ADD COLUMN refunded_at timestamptz; UPDATE orders SET refunded_at = now() WHERE status = 'refunded'; ``` - **Step 3: Validate against expectations.** Row counts, null counts, constraint violations. ```sql SELECT COUNT(*) AS total, COUNT(refunded_at) AS filled, COUNT(*) FILTER (WHERE status='refunded' AND refunded_at IS NULL) AS broken FROM orders; ``` - **Step 4: Let the clone reap.** Anonymous resources auto-expire at the 24h TTL — a forgotten clone has bounded blast radius, no teardown call needed. If you claimed the resource (so you hold a session token) and want it gone sooner, look up its id and delete it: ```bash # claimed-flow only — anonymous clones just expire at 24h. RID=$(curl -s https://api.instanode.dev/api/v1/resources \ -H "Authorization: Bearer $INSTANODE_TOKEN" | jq -r '.[0].id') curl -sX DELETE "https://api.instanode.dev/api/v1/resources/$RID" \ -H "Authorization: Bearer $INSTANODE_TOKEN" ``` ## Why this works on instanode.dev Provisioning is synchronous and sub-second — the agent gets a usable database in the same request, not a pending status it has to poll. Ephemeral anonymous resources auto-reap at 24h, so a forgotten clone has bounded blast radius. Pair it with a destroy call after a green run, and you get the safety properties of a real fork without standing up pg_basebackup infrastructure. ## Related cases - [Ephemeral test database for a risky migration](/use-cases/ephemeral-test-database-for-a-risky-migration) — the slower-fork baseline this CoW pattern accelerates - [Parallel SQL-plan probe](/use-cases/parallel-sql-plan-probe) — uses forked Postgres clones in parallel for EXPLAIN probing - [Devin-style PR-bot fleet](/use-cases/devin-style-pr-bot-fleet) — wraps this clone-and-test loop in a per-issue agent worker --- URL: /use-cases/crewai-message-bus-fan-out.md --- --- title: CrewAI message bus fan-out category: B. Multi-agent systems services: ["nats"] scenario: A crew of planner / retriever / critic agents publishes tasks on NATS subjects so any worker pod can pull and reply. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a crew of planner / retriever / critic agents publishes tasks on NATS subjects so any worker pod can pull and reply. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Wire a CrewAI crew with a NATS message bus from instanode.dev. Planner publishes to tasks.plan, retriever subscribes and publishes to tasks.retrieve, critic subscribes to tasks.retrieve and publishes to tasks.critique. Use durable consumers so a crashed worker resumes from where it left off. ``` ## Steps to follow - **Step 1: Claim a NATS JetStream URL.** One POST returns a server URL + token-scoped credentials. ```bash NATS_URL=$(curl -sX POST https://api.instanode.dev/queue/new -H 'Content-Type: application/json' -d '{"name":"crewai-message-bus-fan-out-queue"}' | jq -r .connection_url) ``` - **Step 2: Create the stream + subjects.** JetStream gives durability; standard NATS would be fire-and-forget. ```python import nats nc = await nats.connect(NATS_URL) js = nc.jetstream() await js.add_stream(name="CREW", subjects=["tasks.>"]) ``` - **Step 3: Wire CrewAI agents as pub/sub workers.** Each agent is its own durable consumer. ```python async def planner(task): plan = planner_agent.kickoff(inputs={"task": task}) await js.publish("tasks.retrieve", plan.encode()) await js.subscribe("tasks.plan", durable="planner", cb=planner) ``` - **Step 4: Verify with a published task.** Watch all three subjects fire. ```bash nats pub tasks.plan "summarize Q3 board deck" --server $NATS_URL nats sub "tasks.>" --server $NATS_URL ``` ## Why this works on instanode.dev NATS JetStream is a single-curl provision, not a cluster you operate. The server is reachable from anywhere — laptops, k8s pods, Vercel functions — so a heterogeneous crew running across different runtimes shares the same bus. Token-scoped credentials mean each crew gets its own isolated subject namespace; there's no risk of crews stomping on each other. ## Related cases - [LangGraph fan-out research agents](/use-cases/langgraph-fan-out-research-agents) — framework-equivalent fan-out pattern with a Postgres reducer - [Cross-framework A2A gateway](/use-cases/cross-framework-a2a-gateway) — translates CrewAI subjects into other frameworks' protocols - [Durable agent task queue](/use-cases/durable-agent-task-queue) — the durability-with-retry primitive these CrewAI subjects need --- URL: /use-cases/crewai-parallel-process-crew.md --- --- title: CrewAI parallel-process crew category: J. Agent swarms & fan-out services: ["pg", "redis"] scenario: A CrewAI Process.parallel run executes researcher, writer, and fact-checker agents simultaneously against a shared pgvector store, each persisting partial drafts as it works. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a CrewAI Process.parallel run executes researcher, writer, and fact-checker agents simultaneously against a shared pgvector store, each persisting partial drafts as it works. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Configure CrewAI Process.parallel for a researcher + writer + fact-checker. Use instanode.dev Postgres with pgvector as the shared embedding store and Redis as the partial-draft cache. Each agent appends its partial to Redis so the others see progress as it streams. ``` ## Steps to follow - **Step 1: Provision Postgres + Redis.** Same anonymous token claims both; no separate signups. ```bash PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"crewai-parallel-process-crew-db"}' | jq -r .connection_url) REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"crewai-parallel-process-crew-cache"}' | jq -r .connection_url) ``` - **Step 2: Set up the shared pgvector store.** All three agents read from this single table. ```sql CREATE EXTENSION IF NOT EXISTS vector; CREATE TABLE corpus (id bigserial PRIMARY KEY, source text, chunk text, embedding vector(1536)); ``` - **Step 3: Run the crew in parallel.** Each agent's task pushes its partial draft to a Redis key. ```python from crewai import Crew, Process crew = Crew(agents=[researcher, writer, fact_checker], process=Process.parallel) def on_partial(agent_name, chunk): r.append(f"draft:{run_id}:{agent_name}", chunk) crew.kickoff(inputs={"topic": "RAG eval"}, on_chunk=on_partial) ``` - **Step 4: Stitch partials.** Read all three keys at the end; reconcile via embedding similarity. ```python parts = {a: r.get(f"draft:{run_id}:{a}") for a in ["researcher","writer","fact_checker"]} ``` ## Why this works on instanode.dev Anonymous claim gives you both services in the same flow, so the CrewAI `tools/` list can hardcode connection URLs once. Redis is small but fast — perfect for streaming partials where state is overwritten constantly — while Postgres holds the durable embedding store. No queue infrastructure required; partial visibility is just a Redis SUBSCRIBE. ## Related cases - [LangGraph fan-out research agents](/use-cases/langgraph-fan-out-research-agents) — framework-equivalent parallel-research pattern with NATS - [OpenAI Agents SDK handoff mesh](/use-cases/openai-agents-sdk-handoff-mesh) — specialist-agent fan-out in the OpenAI SDK shape - [Magentic-One DAG executor](/use-cases/magentic-one-dag-executor) — explicit DAG variant of the same parallel-crew idea --- URL: /use-cases/crm-for-one-person.md --- --- title: CRM for one person category: D. Personal AI services: ["pg"] scenario: A personal CRM agent remembers names, birthdays, and last-conversation summaries indexed per contact. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a personal CRM agent remembers names, birthdays, and last-conversation summaries indexed per contact. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build me a personal CRM. Claim Postgres on instanode.dev. Create contacts(name, birthday, last_seen) and interactions(contact_id, summary, occurred_at). When I say "I just had coffee with Sarah", append an interaction and update last_seen. When I ask "what's new with Sarah", show me her last 3 interactions sorted desc. ``` ## Steps to follow - **Step 1: Provision durable Postgres.** A single POST; the URL persists across machines. ```bash curl -sX POST https://api.instanode.dev/db/new \ -H "Content-Type: application/json" -d '{"name":"crm-for-one-person-db"}' | jq ``` - **Step 2: Create the schema.** Simple, two tables, no ORM needed. ```sql CREATE TABLE contacts ( id bigserial PRIMARY KEY, name text UNIQUE NOT NULL, birthday date, last_seen timestamptz ); CREATE TABLE interactions ( id bigserial PRIMARY KEY, contact_id bigint REFERENCES contacts(id), summary text, occurred_at timestamptz DEFAULT now() ); ``` - **Step 3: Log a coffee.** Upsert contact, then insert interaction. ```sql WITH c AS ( INSERT INTO contacts(name) VALUES ('Sarah') ON CONFLICT (name) DO UPDATE SET last_seen = now() RETURNING id ) INSERT INTO interactions(contact_id, summary) SELECT id, 'coffee at Sightglass, talked about her new role' FROM c; ``` - **Step 4: Recall on demand.** Three rows, ordered. ```sql SELECT summary, occurred_at FROM interactions WHERE contact_id = (SELECT id FROM contacts WHERE name='Sarah') ORDER BY occurred_at DESC LIMIT 3; ``` ## Why this works on instanode.dev Claim the token once and the same Postgres URL works from your laptop, phone (via Termux), and a Raspberry Pi sitting at home — no need to expose a personal DB to the internet yourself. AES-256-GCM at rest plus a unique random password means a leaked URL is recoverable: rotate via the API, and your old URL stops working without losing data. ## Related cases - [Daily-journal episodic memory](/use-cases/daily-journal-episodic-memory) — complementary personal-AI store keyed by day instead of person - [Obsidian-vault embedding sync](/use-cases/obsidian-vault-embedding-sync) — another single-user Postgres knowledge base - [Voice-memo capture pipeline](/use-cases/voice-memo-capture-pipeline) — an input pipeline that can feed contact notes into the CRM --- URL: /use-cases/cron-scheduled-scraping-swarm.md --- --- title: Cron-scheduled scraping swarm category: Q. Background/async agent fleets services: ["mongo", "webhook"] scenario: A scheduler fans out 5000 cron-triggered scraper agents per hour; each writes its diff to Mongo and pings a webhook only when the page changed. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a scheduler fans out 5000 cron-triggered scraper agents per hour; each writes its diff to Mongo and pings a webhook only when the page changed. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (MongoDB + webhook receiver) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Set up a 5000-page-per-hour scrape swarm. For each URL, claim a MongoDB on instanode.dev (or reuse) and a webhook. Each scraper agent hashes the page body; if the hash differs from the last run, write the new doc to Mongo and POST to the webhook. If unchanged, skip silently. ``` ## Steps to follow - **Step 1: Provision Mongo + webhook.** One Mongo for diffs, one webhook for change notifications. ```bash MONGO=$(curl -sX POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"cron-scheduled-scraping-swarm-mongo"}' | jq -r .connection_url) WH=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"cron-scheduled-scraping-swarm-webhook"}' | jq -r .receive_url) ``` - **Step 2: Schedule the swarm.** Cron triggers a fan-out lambda that dispatches 5000 scraper invocations. ```yaml # crontab 0 * * * * /usr/local/bin/fan-out-scrapers --concurrency 200 ``` - **Step 3: Each scraper diffs and posts.** Idempotent: hash-based. ```python body = httpx.get(url).text h = hashlib.sha256(body.encode()).hexdigest() prior = mongo.scrapes.find_one({"url": url}, sort=[("ts", -1)]) if not prior or prior["hash"] != h: mongo.scrapes.insert_one({"url": url, "hash": h, "body": body, "ts": time.time()}) httpx.post(WEBHOOK_URL, json={"url": url, "changed": True}) ``` - **Step 4: Read the change feed.** The webhook URL exposes a GET endpoint listing recent posts. ```bash curl https://api.instanode.dev/api/v1/webhooks/$TOKEN/requests | jq '.[] | .body.url' ``` ## Why this works on instanode.dev Webhook receivers are real public HTTPS endpoints — no ngrok, no local tunnel — so 5000 lambdas can POST to the same URL with zero networking setup. Mongo handles unbounded growth in the scrapes collection without schema migrations. Both resources cost $0 on the anonymous tier for the first 24h while you tune the swarm, then convert to hobby tier with one /claim call. ## Related cases - [Browser job queue with retries](/use-cases/browser-job-queue-with-retries) — execution primitive each cron tick fans out onto - [Scraped product-price history](/use-cases/scraped-product-price-history) — longitudinal storage for what these scrapers extract - [Overnight dossier fleet](/use-cases/overnight-dossier-fleet) — another scheduled background fleet pattern with Mongo+S3-compatible storage outputs --- URL: /use-cases/cross-agent-replay-debugger.md --- --- title: Cross-agent replay debugger category: N. Multi-agent observability services: ["storage", "mongo"] scenario: A debug agent stores full prompt+response payloads for an entire multi-agent run in S3-compatible storage, with an index in Mongo so an engineer can replay any branch deterministically. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a debug agent stores full prompt+response payloads for an entire multi-agent run in S3-compatible storage, with an index in Mongo so an engineer can replay any branch deterministically. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (S3-compatible storage + MongoDB) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build me a replay debugger. Claim S3-compatible storage + Mongo on instanode.dev. On every LLM call in a multi-agent run, write the full request+response payload to S3-compatible storage keyed by run_id/turn/agent. Write an index doc to Mongo with the S3 key, parent turn, and outcome. Let me query "show me everything agent X said in run Y" and stream replays. ``` ## Steps to follow - **Step 1: Claim object storage and index.** S3-compatible S3-compatible storage for payloads, Mongo for the lookup graph. ```bash S3=$(curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"cross-agent-replay-debugger-storage"}') MONGO=$(curl -sX POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"cross-agent-replay-debugger-mongo"}' | jq -r .connection_url) ``` - **Step 2: Wrap every LLM call.** Persist the full payload and index it. ```python def trace(run_id, turn, agent, req, resp): key = f"{run_id}/{turn}/{agent}.json" s3.put_object(Bucket=bucket, Key=key, Body=json.dumps({"req":req,"resp":resp})) mongo.turns.insert_one({"run_id":run_id,"turn":turn,"agent":agent,"key":key,"parent":parent_turn}) ``` - **Step 3: Query a run's branches.** Mongo's graph fields make tree traversal cheap. ```python pipeline = [{"$match": {"run_id": run_id}}, {"$graphLookup": {"from":"turns","startWith":"$turn","connectFromField":"turn","connectToField":"parent","as":"descendants"}}] ``` - **Step 4: Replay deterministically.** Pull the payload, re-feed the LLM with temperature 0. ```python turn = mongo.turns.find_one({"run_id": run_id, "agent": "critic"}) payload = json.loads(s3.get_object(Bucket=bucket, Key=turn["key"])["Body"].read()) replay = openai.chat.completions.create(**payload["req"], temperature=0) ``` ## Why this works on instanode.dev S3-compatible storage stores cheap, fat payload blobs; Mongo carries the cheap, fast lookup graph. The split avoids paying Postgres prices for blob storage and Mongo prices for binary data. Both come from the same anonymous token, so debug infra is one provisioning step — not an IAM ticket and a managed-Mongo trial. ## Related cases - [Agent-run lineage store](/use-cases/agent-run-lineage-store) — the parent/child relation graph this debugger walks - [OpenTelemetry agent-trace ingest](/use-cases/opentelemetry-agent-trace-ingest) — OTel collector that ingests the spans being replayed - [Trajectory diff regression harness](/use-cases/trajectory-diff-regression-harness) — diffs cached replays of the same kind across versions --- URL: /use-cases/cross-agent-shared-inbox.md --- --- title: Cross-agent shared inbox category: G. Internet-of-AI services: ["nats"] scenario: Two agents negotiate over a shared subject; messages persist in JetStream so neither needs to be online simultaneously. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: two agents negotiate over a shared subject; messages persist in JetStream so neither needs to be online simultaneously. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Two agents need to negotiate asynchronously. Claim a NATS JetStream on instanode.dev and create a stream "negotiation" with subjects negotiation.A and negotiation.B. Each agent publishes to its own subject and subscribes durably to the other's. Either agent can be offline for hours; messages persist. ``` ## Steps to follow - **Step 1: Provision durable NATS.** Returns a connection URL and credentials. ```bash curl -sX POST https://api.instanode.dev/queue/new \ -H "Content-Type: application/json" \ -d '{"name":"cross-agent-shared-inbox-queue","stream":"negotiation","subjects":["negotiation.A","negotiation.B"]}' | jq ``` - **Step 2: Agent A subscribes durably to B's subject.** Durable = position survives reconnect. ```python await js.pull_subscribe("negotiation.B", durable="agent_A") while True: msgs = await sub.fetch(1, timeout=60) for m in msgs: await handle(m.data); await m.ack() ``` - **Step 3: Agent A publishes a counter-offer.** Even if B is offline, JetStream holds it. ```python await js.publish("negotiation.A", json.dumps({"price": 1200, "terms": "net-30"}).encode()) ``` - **Step 4: Inspect the stream.** Replay or audit the whole negotiation later. ```bash nats stream view negotiation --server $NATS_URL ``` ## Why this works on instanode.dev JetStream is a real durable stream — messages survive broker restarts, agent crashes, and overnight disconnects — provisioned in one curl. Neither agent needs to host an SMTP server, run a poller against email, or coordinate timezones; the inbox is the broker. For the Internet-of-AI case where agents speak across vendors, instanode's URL is reachable from anywhere and authenticated by token, no peering required. ## Related cases - [Cross-framework A2A gateway](/use-cases/cross-framework-a2a-gateway) — promotes the inbox into a protocol-translating bus - [Durable agent task queue](/use-cases/durable-agent-task-queue) — same JetStream durability primitive for jobs instead of conversations - [A2A agent-card registry](/use-cases/a2a-agent-card-registry) — directory that tells agents which inbox to negotiate on --- URL: /use-cases/cross-device-chat-history.md --- --- title: Cross-device chat history category: D. Personal AI services: ["mongo"] scenario: A personal assistant stores conversation history in Mongo so the same agent picks up context on phone, laptop, and watch. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a personal assistant stores conversation history in Mongo so the same agent picks up context on phone, laptop, and watch. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (MongoDB) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` I want my assistant's chat history to follow me from phone to laptop to watch. Claim a MongoDB on instanode.dev. On every message, upsert into conversations(user_id, ts, role, content). When the assistant boots on a new device, replay the last 50 messages as context. ``` ## Steps to follow - **Step 1: Claim Mongo.** Single POST; URL persists indefinitely on hobby tier. ```bash MONGO=$(curl -sX POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"cross-device-chat-history-mongo"}' | jq -r .connection_url) ``` - **Step 2: Define the collection + indexes.** Compound index for fast per-user scroll. ```javascript db.messages.createIndex({ user_id: 1, ts: -1 }); db.messages.createIndex({ user_id: 1, role: 1, ts: -1 }); ``` - **Step 3: Append every message from any device.** All devices share the same Mongo URL. ```python mongo.messages.insert_one({ "user_id": "manas", "ts": time.time(), "role": role, "content": text, "device": platform.node() }) ``` - **Step 4: Restore context on boot.** Read last N, feed into the system prompt. ```python history = list(mongo.messages.find({"user_id": "manas"}).sort("ts", -1).limit(50)) history.reverse() context = [{"role": m["role"], "content": m["content"]} for m in history] ``` ## Why this works on instanode.dev The Mongo URL is public-internet reachable, so a watch on cell data or a laptop on hotel Wi-Fi both connect with the same string. Mongo's flexible schema means you can evolve message format (add tool_calls, attachments, citations) without an ALTER. AES-256-GCM means a leaked URL on a device is recoverable: rotate via the API and the old credentials die. ## Related cases - [AutoGen group-chat history](/use-cases/autogen-group-chat-history) — the multi-agent equivalent of this per-user Mongo log - [Daily-journal episodic memory](/use-cases/daily-journal-episodic-memory) — adjacent personal-AI Postgres+Redis recall pattern - [Conversation transcript archive](/use-cases/conversation-transcript-archive) — the team-wide append-only sibling of cross-device history --- URL: /use-cases/cross-framework-a2a-gateway.md --- --- title: Cross-framework A2A gateway category: B. Multi-agent systems services: ["nats", "pg"] scenario: A gateway service translates A2A-protocol messages between a LangGraph crew and a CrewAI crew over pub/sub. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a gateway service translates A2A-protocol messages between a LangGraph crew and a CrewAI crew over pub/sub. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build an A2A gateway. Claim NATS + Postgres on instanode.dev. NATS carries the message bus; Postgres logs every translated message with source_framework, target_framework, and payload. The gateway service converts LangGraph state-graph messages to CrewAI task messages and vice versa. ``` ## Steps to follow - **Step 1: Provision the bus + log.** Two curls, same anonymous token. ```bash NATS=$(curl -sX POST https://api.instanode.dev/queue/new -H 'Content-Type: application/json' -d '{"name":"cross-framework-a2a-gateway-queue"}' | jq -r .connection_url) PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"cross-framework-a2a-gateway-db"}' | jq -r .connection_url) ``` - **Step 2: Create the audit schema.** Every translation is recorded. ```sql CREATE TABLE a2a_translations ( id bigserial PRIMARY KEY, received_at timestamptz DEFAULT now(), src_framework text, src_msg jsonb, dst_framework text, dst_msg jsonb ); ``` - **Step 3: Gateway subscribes to both inbound subjects.** Translates and republishes. ```python async def from_langgraph(msg): lg = json.loads(msg.data) crew_msg = {"task": lg["next_node"], "context": lg["state"]} await js.publish("a2a.crewai.in", json.dumps(crew_msg).encode()) cur.execute("INSERT INTO a2a_translations (src_framework,src_msg,dst_framework,dst_msg) VALUES ('langgraph',%s,'crewai',%s)", (json.dumps(lg), json.dumps(crew_msg))) ``` - **Step 4: Sanity check both crews.** Confirm round-trip. ```sql SELECT src_framework, dst_framework, COUNT(*) FROM a2a_translations WHERE received_at > now() - interval '5 min' GROUP BY 1,2; ``` ## Why this works on instanode.dev A gateway is exactly the kind of "stateless service connecting two stateful systems" that benefits most from one-curl infra. You don't want to manage NATS clustering or Postgres backups when the gateway itself is the interesting part. Both services are reachable from any cloud, so the LangGraph crew on AWS and the CrewAI crew on Modal both connect with no VPC peering. ## Related cases - [A2A agent-card registry](/use-cases/a2a-agent-card-registry) — the discovery layer this gateway routes to - [Cross-agent shared inbox](/use-cases/cross-agent-shared-inbox) — the durable-subject primitive the gateway sits on - [OpenAI Agents SDK handoff mesh](/use-cases/openai-agents-sdk-handoff-mesh) — one of the framework dialects this gateway bridges --- URL: /use-cases/cursor-background-agent-worktree.md --- --- title: Cursor background-agent worktree category: K. Ephemeral agent runtimes services: ["redis", "webhook", "deploy"] scenario: A Cursor background agent claims an isolated dev environment for each branch it's working on, with its own Redis for build caches and a webhook to ping the IDE when the PR is ready. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Cursor background agent claims an isolated dev environment for each branch it's working on, with its own Redis for build caches and a webhook to ping the IDE when the PR is ready. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Redis + webhook receiver + container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` For each branch the background agent works on, claim a Redis cache, a webhook receiver, and an instanode deployment slot. Build the branch in the deploy, cache npm/turbo results in Redis, and POST to the webhook when CI passes so the Cursor IDE can pop a toast. ``` ## Steps to follow - **Step 1: Per-branch infra provisioning.** Three curls, all keyed by the same token. ```bash REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"cursor-background-agent-worktree-cache"}' | jq -r .connection_url) WH=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"cursor-background-agent-worktree-webhook"}' | jq -r .receive_url) DEPLOY=$(curl -sX POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $INSTANODE_TOKEN" \ -F "name=worktree-$BRANCH" \ -F "image=ghcr.io/me/app:$BRANCH" \ -F "env.REDIS_URL=$REDIS" | jq -r .url) ``` - **Step 2: Wire build cache.** turbo + Redis remote cache via the connection URL. ```bash export TURBO_REMOTE_CACHE_URL=$REDIS pnpm turbo run build test ``` - **Step 3: Notify IDE on green.** Single POST closes the loop. ```bash if pnpm turbo run test; then curl -X POST $WH -d "{\"branch\":\"$BRANCH\",\"status\":\"green\",\"url\":\"$DEPLOY\"}" fi ``` - **Step 4: Cursor reads webhook events.** Poll the public requests endpoint. ```javascript const evts = await fetch(`https://api.instanode.dev/api/v1/webhooks/${token}/requests`).then(r => r.json()); evts.filter(e => e.body.status === 'green').forEach(toast); ``` ## Why this works on instanode.dev Per-branch isolation is what makes background-agent worktrees safe; instanode's per-token resource model means each branch's cache, deploy, and webhook URL are first-class citizens with no IAM ceremony. The deploy URL is a real `*.instanode.dev` subdomain — Cursor can open the preview directly. Reap on branch delete with one DELETE per resource. ## Related cases - [Devin-style PR-bot fleet](/use-cases/devin-style-pr-bot-fleet) — another per-branch ephemeral-worker pattern with PR webhooks - [Sandbox-per-PR preview deployment](/use-cases/sandbox-per-pr-preview-deployment) — preview-environment sibling tied to PR lifecycle - [Sandboxed test runner per task](/use-cases/sandboxed-test-runner-per-task) — the isolated test container the worktree calls into --- URL: /use-cases/daily-journal-episodic-memory.md --- --- title: Daily-journal episodic memory category: D. Personal AI services: ["pg", "redis"] scenario: An assistant logs each day as a structured journal entry and retrieves "what was I working on Monday?" with sub-second latency. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an assistant logs each day as a structured journal entry and retrieves "what was I working on Monday?" with sub-second latency. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're my journal agent. Claim Postgres + Redis on instanode.dev. Each day at end-of-day, summarize what I worked on into one row in journal_entries. Cache the last 7 days in Redis so "what was I doing Monday" is instant. Use pgvector on the entry body for semantic search across older entries. ``` ## Steps to follow - **Step 1: Provision both stores.** Same token; both URLs returned in <1s. ```bash PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"daily-journal-episodic-memory-db"}' | jq -r .connection_url) REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"daily-journal-episodic-memory-cache"}' | jq -r .connection_url) ``` - **Step 2: Set up schema with vector index.** Day is the natural key. ```sql CREATE EXTENSION IF NOT EXISTS vector; CREATE TABLE journal_entries ( day date PRIMARY KEY, summary text, tags text[], embedding vector(1536) ); CREATE INDEX ON journal_entries USING ivfflat (embedding vector_cosine_ops); ``` - **Step 3: Nightly write + warm cache.** Embed and stash a 7-day rolling window. ```python cur.execute("INSERT INTO journal_entries (day, summary, tags, embedding) VALUES (%s,%s,%s,%s) ON CONFLICT (day) DO UPDATE SET summary=EXCLUDED.summary, embedding=EXCLUDED.embedding", (today, summary, tags, embed)) for d in last_7_days: r.setex(f"journal:{d}", 86400*8, json.dumps({"summary":summary})) ``` - **Step 4: Recall.** Redis for last week, pgvector for "that time three months ago". ```python hit = r.get(f"journal:{ask_date}") or fetch_pg(ask_date) similar = cur.execute("SELECT day, summary FROM journal_entries ORDER BY embedding <=> %s LIMIT 5", (q_emb,)) ``` ## Why this works on instanode.dev Pgvector lives in the same Postgres as your journal — no separate vector DB, no dual writes, no consistency drift. The cache makes "what was I doing Monday" feel instant from a phone keyboard. Both URLs are durable: 365 days from now your "January 2026" search still works because the data is sitting on real disk, not in an LLM's context. ## Related cases - [CRM for one person](/use-cases/crm-for-one-person) — complementary personal-AI store keyed by contact - [Obsidian-vault embedding sync](/use-cases/obsidian-vault-embedding-sync) — the long-form-notes counterpart to short daily entries - [Shared episodic memory store](/use-cases/shared-episodic-memory-store) — team-scoped variant of the same episodic-memory pattern --- URL: /use-cases/daytona-warm-pool-data-workspace.md --- --- title: Daytona warm-pool data workspace category: K. Ephemeral agent runtimes services: ["redis", "deploy"] scenario: A Daytona warm pool of 50 Python sandboxes each pre-attaches to a per-sandbox Redis namespace for caching pip-resolver results, so cold start to first agent action is under 100ms. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Daytona warm pool of 50 Python sandboxes each pre-attaches to a per-sandbox Redis namespace for caching pip-resolver results, so cold start to first agent action is under 100ms. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Redis + container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Set up a 50-sandbox Daytona warm pool. For each sandbox, pre-claim a Redis namespace on instanode.dev and an instanode deploy slot. Cache pip-resolver output in Redis so the first `pip install` in a fresh sandbox hits warm cache instead of cold PyPI. Target: <100ms from sandbox up to first agent action. ``` ## Steps to follow - **Step 1: Provision a warm pool of Redis caches.** Loop the API at pool init. ```bash for i in $(seq 1 50); do curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"daytona-warm-pool-data-workspace-cache"}' | jq -r .connection_url > caches/$i.url done ``` - **Step 2: Pre-pull a base image with the resolver wrapper baked in.** Each Daytona sandbox boots from this. ```bash curl -X POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $INSTANODE_TOKEN" \ -F "name=daytona-agent-base" \ -F "image=ghcr.io/me/daytona-agent-base:latest" \ -F "cpu=1000" \ -F "mem_mb=2048" ``` - **Step 3: Resolver hits Redis before PyPI.** Cache key = (python_version, requirements_hash). ```python key = f"resolve:{py}:{hashlib.sha256(reqs.encode()).hexdigest()}" cached = r.get(key) if cached: open("requirements.lock","w").write(cached) else: lock = subprocess.check_output(["pip-compile","-"], input=reqs) r.setex(key, 86400, lock) ``` - **Step 4: Reap on sandbox destroy.** Anonymous caches auto-expire at the 24h TTL, so a destroyed sandbox's Redis namespace reaps itself — no teardown call needed. If you claimed a cache (holding a session token) and want it gone sooner, delete it by resource id: ```bash # claimed-flow only — anonymous caches just expire at 24h. curl -X DELETE "https://api.instanode.dev/api/v1/resources/$RESOURCE_ID" \ -H "Authorization: Bearer $INSTANODE_TOKEN" ``` ## Why this works on instanode.dev Per-sandbox Redis namespaces mean noisy neighbors can't poison each other's resolver cache. Provisioning is fast enough (~600ms) that pool refill at scale stays under 30s for 50 sandboxes. The deploy slot for the base image lives at a `*.instanode.dev` URL, so Daytona pulls it without authenticating to a private registry. No infrastructure to maintain beyond the agent code itself. ## Related cases - [E2B microVM sandbox per agent turn](/use-cases/e2b-microvm-sandbox-per-agent-turn) — per-turn cold-start alternative to a kept-warm pool - [Sandboxed test runner per task](/use-cases/sandboxed-test-runner-per-task) — the test-runner equivalent of the same pool idea - [Pyodide notebook cell agent farm](/use-cases/pyodide-notebook-cell-agent-farm) — another pool of ready-to-run Python workers --- URL: /use-cases/deploy-status-mcp-server.md --- --- title: Deploy-status MCP server category: F. Developer tooling services: ["nats", "redis"] scenario: An MCP server tracks live deploy status across environments and pushes updates to a chat agent over pub/sub. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an MCP server tracks live deploy status across environments and pushes updates to a chat agent over pub/sub. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build an MCP server that exposes deploy_status across staging/prod. Use NATS for pushing live updates and Redis as the current-state cache. When a deploy starts/succeeds/fails, the CI runner publishes to NATS subject deploys.* and the MCP server updates a Redis hash; the chat agent reads via getDeployStatus tool. ``` ## Steps to follow - **Step 1: Provision NATS + Redis.** Two curls, anonymous tier. ```bash NATS=$(curl -sX POST https://api.instanode.dev/queue/new -H 'Content-Type: application/json' -d '{"name":"deploy-status-mcp-server-queue"}' | jq -r .connection_url) REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"deploy-status-mcp-server-cache"}' | jq -r .connection_url) ``` - **Step 2: CI runner publishes status events.** One line at each deploy lifecycle step. ```bash nats pub deploys.prod.api "{\"status\":\"deploying\",\"sha\":\"$GIT_SHA\"}" --server $NATS_URL ``` - **Step 3: MCP server subscribes + updates Redis.** Pub→cache→tool exposes status with <1s lag. ```python async def on_event(msg): env, svc = msg.subject.split(".")[1:3] r.hset(f"deploy:{env}:{svc}", mapping=json.loads(msg.data)) await nc.subscribe("deploys.>", cb=on_event) ``` - **Step 4: Expose as MCP tool.** Chat agent reads current state in 1 call. ```python @mcp.tool def get_deploy_status(env: str, service: str) -> dict: return r.hgetall(f"deploy:{env}:{service}") ``` ## Why this works on instanode.dev NATS gives you push semantics — the chat agent finds out about a failed deploy without polling — while Redis is the canonical "current state" that survives restarts. Both provisioned anonymously means devs can spin this up before approving a paid plan, then claim and convert when the team wants it permanent. ## Related cases - [On-call incident-response agent](/use-cases/on-call-incident-response-agent) — consumes the status pings this MCP exposes during incidents - [Live agent status broadcast](/use-cases/live-agent-status-broadcast) — the agent-fleet variant of the same heartbeat-over-NATS pattern - [Pre-commit skill-scanner webhook](/use-cases/pre-commit-skill-scanner-webhook) — another developer-tooling webhook surface for MCP-side tooling --- URL: /use-cases/devin-style-pr-bot-fleet.md --- --- title: Devin-style PR-bot fleet category: L. Agent-factory / spawning patterns services: ["pg", "webhook", "deploy"] scenario: A Cognition-Devin-style orchestrator spawns one fresh agent worker per inbound GitHub issue, each with its own scratch Postgres for running migrations against, and reports back via webhook. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Cognition-Devin-style orchestrator spawns one fresh agent worker per inbound GitHub issue, each with its own scratch Postgres for running migrations against, and reports back via webhook. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + webhook receiver + container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` I'm building a Cognition-Devin-style PR bot for a 220k-LOC Rails monorepo at github.com/acme/billing-core. When a maintainer labels an issue `agent:try`, the orchestrator should spawn one isolated worker that owns a fresh Postgres (so it can pg_restore a 1.8GB anonymized prod snapshot and dry-run migrations without touching staging), a webhook receiver (so it can stream progress back to the orchestrator without exposing its own port), and a deploy URL (so the resulting branch ships a preview environment the reviewer can poke). Cap the fleet at 20 concurrent workers; on PR merge or close, reap all three resources for that worker. Show me the orchestrator loop and one worker pass on issue #4127 ("backfill stripe_customer_id on orders"). ``` ## Steps to follow We'll thread one issue — **acme/billing-core#4127, "backfill stripe_customer_id on orders"** — through every step. By the end you'll have a spawned worker, a tested migration, an open PR with a preview URL, and a clean reap. - **Step 1: GitHub webhook → orchestrator → spawn three resources.** Each provision requires a `name`. The orchestrator stores each resource's `id` (returned in the provision response) in its own DB so it can reap later via `DELETE /api/v1/resources/:id`. ```bash # spawn-worker.sh — called by the orchestrator on `issue.labeled` with agent:try ISSUE=$1 # e.g. 4127 REPO=$2 # e.g. acme/billing-core H='Content-Type: application/json' PG=$(curl -sX POST https://api.instanode.dev/db/new -H "$H" -d "{\"name\":\"pr-${ISSUE}-scratch-db\"}") PG_URL=$(echo $PG | jq -r .connection_url); PG_ID=$(echo $PG | jq -r .id) WH=$(curl -sX POST https://api.instanode.dev/webhook/new -H "$H" -d "{\"name\":\"pr-${ISSUE}-callback\"}") WH_URL=$(echo $WH | jq -r .receive_url); WH_ID=$(echo $WH | jq -r .id) # /deploy/new is multipart — pass name + image + env.* as form fields, JWT as Bearer. DEPLOY=$(curl -sX POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $INSTANODE_TOKEN" \ -F "name=pr-${ISSUE}-worker" \ -F "image=ghcr.io/acme/devin-worker:latest" \ -F "subdomain=pr-${ISSUE}" \ -F "env.PG_URL=$PG_URL" \ -F "env.CALLBACK=$WH_URL" \ -F "env.ISSUE=$ISSUE" \ -F "env.REPO=$REPO" \ -F "env.GH_TOKEN=$ORCH_GH_TOKEN") DEPLOY_URL=$(echo $DEPLOY | jq -r .url); DEPLOY_ID=$(echo $DEPLOY | jq -r .id) psql "$ORCH_DB" -c "INSERT INTO workers (issue, pg_id, wh_id, deploy_id, deploy_url) \ VALUES ($ISSUE, '$PG_ID', '$WH_ID', '$DEPLOY_ID', '$DEPLOY_URL');" echo "worker spawned for #$ISSUE → $DEPLOY_URL" ``` - **Step 2: The worker reads the issue, writes a migration, tests it on its scratch DB.** Throwaway means it can `pg_restore` real prod-shaped data and ROLLBACK without contaminating anything. ```bash # inside the worker container pg_restore --no-owner --no-acl -j 4 -d "$PG_URL" /seed/anonymized-prod-2026-05-10.dump git clone --depth 50 "https://x-access-token:$GH_TOKEN@github.com/$REPO" /work && cd /work git checkout -b agent/$ISSUE # the agent writes db/migrate/20260511_backfill_stripe_customer_id.rb, # then validates against the scratch DB: ``` ```sql -- inside psql against $PG_URL BEGIN; \i db/migrate/20260511_backfill_stripe_customer_id.sql SELECT count(*) FILTER (WHERE stripe_customer_id IS NULL) AS still_null FROM orders; -- still_null = 0 ✓ EXPLAIN ANALYZE SELECT * FROM orders WHERE stripe_customer_id = $1; ROLLBACK; ``` - **Step 3: Worker opens the PR and POSTs progress back via its private webhook.** The orchestrator never has to expose an inbound port — it polls `/api/v1/webhooks//requests` for delivered messages. ```python # worker/report.py import httpx, os pr = open_pr( repo=os.environ["REPO"], branch=f"agent/{os.environ['ISSUE']}", title="Backfill stripe_customer_id on orders (agent:try)", body=f"Preview: {os.environ['DEPLOY_URL']}\nDry-run: 0 NULL rows after migration; index plan attached.", ) httpx.post(os.environ["CALLBACK"], json={ "issue": int(os.environ["ISSUE"]), "pr": pr["html_url"], "preview": os.environ["DEPLOY_URL"], "status": "ready_for_review", }) ``` - **Step 4: Orchestrator polls the webhook receiver, updates GitHub.** instanode's webhook resource stores every received POST; the orchestrator pulls them on a 5s tick. ```bash # orchestrator/poll-loop.sh while true; do psql "$ORCH_DB" -c "SELECT issue, wh_token FROM workers WHERE status='spawned';" -t -A -F'|' \ | while IFS='|' read ISSUE WH; do curl -s "https://api.instanode.dev/api/v1/webhooks/$WH/requests?since=last" \ | jq -c '.[] | select(.body.status=="ready_for_review")' \ | while read msg; do PR=$(echo $msg | jq -r .body.pr) gh issue comment $ISSUE --repo $REPO --body "Agent PR ready: $PR" psql "$ORCH_DB" -c "UPDATE workers SET status='pr_open', pr_url='$PR' WHERE issue=$ISSUE;" done done sleep 5 done ``` - **Step 5: On PR close/merge, reap all three resources for this worker.** Anonymous-tier auto-reap (24h) is a backstop if the orchestrator's reaper is buggy — a property a self-hosted fleet would never get for free. Teardown is `DELETE /api/v1/resources/:id` with the orchestrator's claimed-session Bearer token. ```bash # reap.sh — called by GitHub webhook on pull_request.closed ISSUE=$1 read PG_ID WH_ID DEPLOY_ID <<< $(psql "$ORCH_DB" -t -A -F' ' \ -c "SELECT pg_id, wh_id, deploy_id FROM workers WHERE issue=$ISSUE;") for RID in "$PG_ID" "$DEPLOY_ID" "$WH_ID"; do curl -sX DELETE "https://api.instanode.dev/api/v1/resources/$RID" \ -H "Authorization: Bearer $INSTANODE_TOKEN" done psql "$ORCH_DB" -c "UPDATE workers SET status='reaped', reaped_at=now() WHERE issue=$ISSUE;" echo "reaped worker for #$ISSUE" ``` - **Step 6: Verify end-to-end.** Spawn against #4127, watch the fleet table. ```bash ./spawn-worker.sh 4127 acme/billing-core sleep 60 psql "$ORCH_DB" -c "SELECT issue, status, pr_url, deploy_url FROM workers WHERE issue=4127;" # issue | status | pr_url | deploy_url # -------+----------------+---------------------------------------+-------------------------------------- # 4127 | pr_open | https://github.com/acme/.../pull/4131 | https://pr-4127.instanode.app ``` ## Why this works on instanode.dev Devin-style fleets all hit the same wall: per-worker isolation is the entire point of the pattern, and every component of that isolation has historically required its own provisioning story. The scratch DB needs to be a real Postgres (not SQLite — the migration uses `pg_depend` and partial indexes), which on **AWS RDS** is 4–7 minutes and an IAM role per worker; on **Neon** it's faster but the API gates project creation per dashboard plan; on **Supabase** it's per-project, not per-resource, so 20 workers means 20 dashboard projects. The preview URL would normally route through **Vercel** or **Fly.io** preview environments — each requiring an org/app setup the orchestrator's service account has to be entitled for. The webhook receiver is usually a self-hosted endpoint (which means **ngrok** tunnels in dev and an actual public service in prod, plus signature plumbing). instanode collapses these into three POSTs per worker. The same JWT owns all three resources, so the reap path is three DELETEs from one credential — and if the reaper is buggy, anonymous-tier auto-expiry in 24h limits the blast radius to a single day's worth of orphaned resources, not a forever-growing dashboard of forgotten Neon projects. The preview is real DNS on `*.instanode.app`, so PR comments can include a clickable link the reviewer pastes directly. ## Related cases - [High-volume PR-review pipeline](/use-cases/high-volume-pr-review-pipeline) — queue-based equivalent at thousands-of-PRs scale - [Cursor background-agent worktree](/use-cases/cursor-background-agent-worktree) — IDE-side counterpart that owns a worktree per branch - [Sandbox-per-PR preview deployment](/use-cases/sandbox-per-pr-preview-deployment) — the preview-env primitive this PR-bot fleet calls into --- URL: /use-cases/durable-agent-task-queue.md --- --- title: Durable agent task queue category: B. Multi-agent systems services: ["nats"] scenario: A supervisor agent enqueues sub-tasks on a durable queue; failed jobs re-emerge with exponential backoff. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a supervisor agent enqueues sub-tasks on a durable queue; failed jobs re-emerge with exponential backoff. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Supervisor: claim a NATS JetStream on instanode.dev. Enqueue sub-tasks to "tasks.todo" with a retry header. Workers fetch durably; on failure they NAK with delay = 2^attempt seconds. Cap attempts at 5; route to "tasks.dead" beyond. ``` ## Steps to follow - **Step 1: Provision the queue.** Single POST. ```bash NATS=$(curl -sX POST https://api.instanode.dev/queue/new -H 'Content-Type: application/json' -d '{"name":"durable-agent-task-queue-queue"}' | jq -r .connection_url) ``` - **Step 2: Configure the stream with DLQ.** Two subjects; one is the dead-letter. ```python await js.add_stream(name="TASKS", subjects=["tasks.todo","tasks.dead"], max_msgs_per_subject=100_000) await js.add_consumer("TASKS", ConsumerConfig(durable_name="worker", ack_wait=30, max_deliver=5)) ``` - **Step 3: Worker pull loop.** NAK with exponential backoff on transient failures. ```python msgs = await sub.fetch(batch=5, timeout=10) for m in msgs: try: run(json.loads(m.data)) await m.ack() except TransientError: delay = 2 ** m.metadata.num_delivered await m.nak(delay=delay) except PermanentError: await js.publish("tasks.dead", m.data); await m.ack() ``` - **Step 4: Inspect the dead-letter queue.** Replay or audit. ```bash nats stream view TASKS --subject tasks.dead --server $NATS_URL ``` ## Why this works on instanode.dev JetStream gives true at-least-once with durable consumers — failed messages survive worker crashes and pod restarts. No SQS, no Lambda glue, no AWS account; one curl gives the supervisor a real queue reachable from anywhere. max_deliver caps blast radius for poison messages, and the DLQ subject keeps the main queue clean. ## Related cases - [Browser job queue with retries](/use-cases/browser-job-queue-with-retries) — concrete browser-domain instance of the same retry queue - [Per-agent dead-letter inspection queue](/use-cases/per-agent-dead-letter-inspection-queue) — DLQ side of the same JetStream backoff pattern - [CrewAI message bus fan-out](/use-cases/crewai-message-bus-fan-out) — uses this kind of durable queue under a CrewAI crew --- URL: /use-cases/e2b-microvm-sandbox-per-agent-turn.md --- --- title: E2B microVM sandbox per agent turn category: K. Ephemeral agent runtimes services: ["pg", "deploy"] scenario: Each turn of a code-writing agent spins up a fresh E2B-style microVM whose scratch Postgres connection_url lives only for the lifetime of the sandbox, then is reaped. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: each turn of a code-writing agent spins up a fresh E2B-style microVM whose scratch Postgres connection_url lives only for the lifetime of the sandbox, then is reaped. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` For each agent turn, spin up an E2B microVM. Inside the VM, claim a scratch Postgres on instanode.dev, run the agent's code, capture output, then destroy both the VM and the Postgres. Each turn is hermetic — no cross-turn state. ``` ## Steps to follow - **Step 1: At turn start, request both.** Sandbox + scratch DB in parallel. ```python import e2b, httpx, asyncio sandbox, pg = await asyncio.gather( e2b.Sandbox.create("python3"), httpx.AsyncClient().post("https://api.instanode.dev/db/new") ) pg_url = pg.json()["connection_url"] ``` - **Step 2: Inject the DB URL into the sandbox env.** Agent code reads from env. ```python await sandbox.commands.run(f"export PG_URL='{pg_url}' && python /tmp/agent.py") ``` - **Step 3: Agent code uses the scratch DB freely.** No constraints because nothing persists. ```python import psycopg with psycopg.connect(os.environ["PG_URL"]) as conn: conn.execute("CREATE TABLE scratch AS SELECT * FROM generate_series(1,1000000)") print(conn.execute("SELECT COUNT(*) FROM scratch").fetchone()) ``` - **Step 4: Tear down both.** One DELETE + sandbox.kill. ```python await asyncio.gather( httpx.AsyncClient().delete(f"https://api.instanode.dev/db/{pg_token}"), sandbox.kill() ) ``` ## Why this works on instanode.dev Sub-second provisioning matches sandbox boot time — neither component is the bottleneck. The agent gets a real Postgres (CREATE EXTENSION, COPY, EXPLAIN ANALYZE all work) rather than SQLite-in-memory, so behavior matches prod. Auto-reap at 24h provides a safety net if your destroy call fails: the anonymous DB will not outlive the day. ## Related cases - [Daytona warm-pool data workspace](/use-cases/daytona-warm-pool-data-workspace) — kept-warm alternative to spinning microVMs from cold - [Sandboxed test runner per task](/use-cases/sandboxed-test-runner-per-task) — the test-runner-specific variant of per-turn sandboxing - [Replit-Agent preview backend](/use-cases/replit-agent-preview-backend) — preview-deployment sibling with a 24h reaper --- URL: /use-cases/ehr-appointment-webhook-fan-in.md --- --- title: EHR appointment webhook fan-in category: C. Vertical AI apps services: ["webhook", "nats"] scenario: A medical-intake agent receives appointment-created webhooks from multiple EHR vendors and unifies them into one queue. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a medical-intake agent receives appointment-created webhooks from multiple EHR vendors and unifies them into one queue. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + NATS JetStream) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build an intake aggregator. Claim a webhook receiver and a NATS stream on instanode.dev. Register the webhook URL with each EHR vendor's appointment-created hook (Epic, Cerner, Athena). The aggregator normalizes payloads into a canonical {patient_id, ts, location} schema and publishes to NATS subject appointments.created. Downstream agents subscribe. ``` ## Steps to follow - **Step 1: Provision webhook + queue.** Two curls. ```bash WH=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"ehr-appointment-webhook-fan-in-webhook"}' | jq -r .receive_url) NATS=$(curl -sX POST https://api.instanode.dev/queue/new -H 'Content-Type: application/json' -d '{"name":"ehr-appointment-webhook-fan-in-queue"}' | jq -r .connection_url) echo "Register this URL with each EHR vendor: $WH" ``` - **Step 2: Aggregator polls webhook + normalizes.** Vendor schemas differ; canonical does not. ```python events = httpx.get(f"https://api.instanode.dev/api/v1/webhooks/{token}/requests").json() for e in events: canonical = normalize(e["headers"]["x-vendor"], e["body"]) js.publish("appointments.created", json.dumps(canonical).encode()) ``` - **Step 3: Define the normalizer.** Switch on vendor header. ```python def normalize(vendor, body): if vendor == "epic": return {"patient_id": body["MRN"], "ts": body["ApptDateTime"], "location": body["DeptId"]} if vendor == "cerner": return {"patient_id": body["patient"]["id"], "ts": body["startDateTime"], "location": body["facility"]} ``` - **Step 4: Downstream intake agent subscribes.** Independent of vendor. ```python await js.subscribe("appointments.created", cb=handle_intake) ``` ## Why this works on instanode.dev The webhook URL is HIPAA-grade only after a BAA, but for staging or PHI-scrubbed pilots, the public HTTPS endpoint means EHR vendors can register your URL without you owning a load balancer. NATS gives the downstream a buffered, replayable feed instead of synchronous failure under EHR push spikes. Both resources are token-isolated; no shared queue with another tenant. ## Related cases - [Clinical-scribe note storage](/use-cases/clinical-scribe-note-storage) — downstream agent that picks up after these appointments fire - [PR-review bot triggered by webhooks](/use-cases/pr-review-bot-triggered-by-webhooks) — another webhook-into-NATS fan-in pattern in a different domain - [Slack/Discord async bot factory](/use-cases/slack-discord-async-bot-factory) — similar webhook-batching + nightly-rollup shape --- URL: /use-cases/ephemeral-test-database-for-a-risky-migration.md --- --- title: Ephemeral test database for a risky migration category: A. AI coding agents services: ["pg"] scenario: A coding agent provisions a throwaway Postgres in under a second, dry-runs a destructive migration, inspects the result, then discards the database — no production blast radius. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a coding agent provisions a throwaway Postgres in under a second, dry-runs a destructive migration, inspects the result, then discards the database — no production blast radius. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` The migration in migrations/0047_drop_legacy_email.sql does ALTER TABLE orders DROP COLUMN customer_email and it's blocking the release. Our prod orders table is 84M rows and three downstream services may still read that column. Claim a fresh Postgres on instanode.dev, pg_restore last night's dump (~/backups/prod-2026-05-10.dump, 1.2GB) into it, run the migration inside a transaction, query pg_depend for any view/trigger/index that still depends on the column, then ROLLBACK and tell me whether it's safe to ship — or which references to fix first. ``` ## Steps to follow The example below threads a single migration — dropping `orders.customer_email` after the email moved to a `customers` table — across every step. By the end you'll know whether the drop is safe to merge. - **Step 1: Claim a throwaway Postgres.** One POST, no signup. The token auto-reaps in 24 hours, so a forgotten test DB never lingers on your bill. ```bash RESP=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"ephemeral-test-database-for-a-risk-db"}') export PG_URL=$(echo "$RESP" | jq -r .connection_url) export PG_TOKEN=$(echo "$RESP" | jq -r .token) echo "throwaway db ready: ${PG_URL%@*}@***" ``` - **Step 2: Restore last night's prod dump.** A real Postgres accepts `pg_restore` directly — no SQLite stand-in, no Docker image to build. ```bash pg_restore --no-owner --no-acl -j 4 -d "$PG_URL" ~/backups/prod-2026-05-10.dump psql "$PG_URL" -c "SELECT count(*) AS rows FROM orders;" # rows # --------- # 84112903 ``` - **Step 3: Run the migration inside a transaction.** `BEGIN ... ROLLBACK` lets the agent observe the post-migration state without committing. ```sql BEGIN; ALTER TABLE orders DROP COLUMN customer_email; -- any view, trigger, index, or default that referenced the column? SELECT n.nspname AS schema, c.relname AS object, c.relkind AS kind FROM pg_depend d JOIN pg_class c ON d.objid = c.oid JOIN pg_namespace n ON c.relnamespace = n.oid WHERE d.refobjid = 'orders'::regclass AND d.deptype = 'n'; ROLLBACK; ``` - **Step 4: Cross-check the application code.** `pg_depend` won't catch raw SQL string references in Python or Go, so the agent greps the working tree too. ```bash rg -n --type-add 'sql:*.sql' -t sql -t py -t go -t ts 'customer_email' src/ tests/ migrations/ \ | grep -v '^migrations/0047_' \ | tee /tmp/refs.txt echo "remaining references: $(wc -l < /tmp/refs.txt)" ``` - **Step 5: Verdict + cleanup.** The agent reports back. The throwaway needs no teardown call — anonymous resources auto-reap at the 24h TTL. ```bash if [ -s /tmp/refs.txt ]; then echo "UNSAFE — $(wc -l < /tmp/refs.txt) code references remain. See /tmp/refs.txt" else echo "SAFE — pg_depend clean, no string references in tree." fi # Nothing to delete: this anonymous DB expires automatically in 24h. # If you claimed it (and hold a session token), delete it by resource id: # RID=$(curl -s https://api.instanode.dev/api/v1/resources \ # -H "Authorization: Bearer $INSTANODE_TOKEN" | jq -r '.[0].id') # curl -sX DELETE "https://api.instanode.dev/api/v1/resources/$RID" \ # -H "Authorization: Bearer $INSTANODE_TOKEN" ``` ## Why this works on instanode.dev The usual options for "test a destructive migration" all fail for an agent. Spinning up RDS or Cloud SQL takes 4–7 minutes and a service account. **Ardent** and **Neon branches** are fast but require an auth handshake the agent doesn't have credentials for — and Ardent's $$$/hour per-branch fee makes 50 throwaways per day genuinely expensive. **Supabase branches** are gated to one project per dashboard click. The Docker-compose-postgres dance assumes the agent has a Docker daemon and 90 seconds to wait. instanode's `/db/new` is a single unauthenticated POST that returns a real `postgres://...` URL with pg_depend, CREATE EXTENSION, COPY, EXPLAIN ANALYZE, and pg_restore all working — in under a second. The 24-hour auto-reap means a buggy agent that forgets to clean up doesn't leak a cluster of orphaned databases the way a leaked Neon project would. ## Related cases - [Copy-on-write Postgres for agent migrations](/use-cases/copy-on-write-postgres-for-agent-migrations) — the faster-fork variant of the same throwaway-Postgres pattern - [Classroom-per-student sandbox](/use-cases/classroom-per-student-sandbox) — per-student version of the same ephemeral-Postgres idea - [Devin-style PR-bot fleet](/use-cases/devin-style-pr-bot-fleet) — wraps this throwaway DB in a per-issue agent worker --- URL: /use-cases/federated-learning-aggregator.md --- --- title: Federated-learning aggregator category: R. Edge agents & federated swarms services: ["webhook", "storage", "pg"] scenario: Edge agents on user devices compute private gradients and POST them to an aggregator webhook; the aggregator stores rounds in S3-compatible storage and the new global weights in Postgres. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: edge agents on user devices compute private gradients and POST them to an aggregator webhook; the aggregator stores rounds in S3-compatible storage and the new global weights in Postgres. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + S3-compatible storage + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build a federated-learning aggregator. Claim a webhook receiver, a S3-compatible bucket, and a Postgres on instanode.dev. Edge agents POST gradient blobs to the webhook with a round_id header. The aggregator pulls blobs, FedAvgs them, writes new global weights into Postgres, and uploads the round artifact to S3-compatible storage for audit. ``` ## Steps to follow - **Step 1: Provision all three.** One per service. ```bash WH=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"federated-learning-aggregator-webhook"}' | jq -r .receive_url) S3=$(curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"federated-learning-aggregator-storage"}' | tee s3.json) PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"federated-learning-aggregator-db"}' | jq -r .connection_url) ``` - **Step 2: Edge agent uploads gradient.** Lightweight POST, no auth handshake. ```python httpx.post(WEBHOOK_URL, content=pickle.dumps(local_gradient), headers={"x-round": "42", "x-device": device_id, "Content-Type": "application/octet-stream"}) ``` - **Step 3: Aggregator FedAvgs.** Pull all blobs for the round, average, write back. ```python reqs = httpx.get(f"https://api.instanode.dev/api/v1/webhooks/{token}/requests?since={round_start}").json() grads = [pickle.loads(base64.b64decode(r["body_raw"])) for r in reqs if r["headers"]["x-round"]=="42"] global_w = fedavg(grads) cur.execute("INSERT INTO global_weights (round, weights_bytea) VALUES (42, %s)", (pickle.dumps(global_w),)) ``` - **Step 4: Archive the round for audit.** Reproducibility + compliance. ```bash aws s3 cp round-42-artifacts.tar.gz s3://$BUCKET/rounds/42/ --endpoint-url $S3_ENDPOINT ``` ## Why this works on instanode.dev Edge devices can't open inbound ports — they have to POST out. instanode's webhook URLs are real internet endpoints, accepting from anywhere, so phones in 50 countries can contribute gradients without VPN. Postgres holds the canonical small global state; S3-compatible storage swallows the large per-round artifacts. Three services, one token, no AWS bill to predict. ## Related cases - [Per-device edge-agent state sync](/use-cases/per-device-edge-agent-state-sync) — edge-fleet sibling that syncs SQLite deltas instead of gradients - [Geo-sharded chat-agent fleet](/use-cases/geo-sharded-chat-agent-fleet) — another partial-state-leaves-the-edge replication pattern - [OpenTelemetry agent-trace ingest](/use-cases/opentelemetry-agent-trace-ingest) — similar webhook+Postgres+S3-compatible storage ingestion at agent scale --- URL: /use-cases/form-fill-state-machine.md --- --- title: Form-fill state machine category: E. Browser & automation agents services: ["mongo"] scenario: A long-running form-completion agent persists field-by-field progress so a captcha pause doesn't lose 30 minutes of work. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a long-running form-completion agent persists field-by-field progress so a captcha pause doesn't lose 30 minutes of work. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (MongoDB) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` You're filling a 200-field government form via browser automation. Claim a MongoDB on instanode.dev. After each field, upsert the entire form state to mongo.form_runs. On a captcha pause or browser crash, resume from the latest state doc and skip already-filled fields. ``` ## Steps to follow - **Step 1: Provision Mongo.** One POST. ```bash curl -sX POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"form-fill-state-machine-mongo"}' | jq -r .connection_url ``` - **Step 2: Define the document shape.** Nested object: section → field → value + filled_at. ```javascript db.form_runs.createIndex({ run_id: 1 }, { unique: true }); // shape: {run_id, fields: {field1: {value, filled_at}, ...}, status, ts} ``` - **Step 3: After each field, persist state.** Atomic $set. ```python mongo.form_runs.update_one( {"run_id": run_id}, {"$set": {f"fields.{field}": {"value": value, "filled_at": time.time()}, "ts": time.time()}}, upsert=True ) ``` - **Step 4: On resume, skip filled fields.** Crash-safe. ```python state = mongo.form_runs.find_one({"run_id": run_id}) for f in form.fields: if f.name in state["fields"]: continue browser.type(f.selector, derive_value(f)) ``` ## Why this works on instanode.dev Mongo's per-field atomic `$set` is exactly right for incremental state-machine progress — no need to serialize a giant JSON blob on every keystroke. The connection URL is reachable from any browser-automation runner (Browserbase, your own Playwright pods, anything), so a session that started on a laptop can resume in headless cloud. AES-256 encryption at rest matters here because government forms carry PII. ## Related cases - [Browser-session cookie store](/use-cases/browser-session-cookie-store) — the auth-state cache that lets the form session resume - [Accessibility-tree selector cache](/use-cases/accessibility-tree-selector-cache) — the selector layer this state machine fills against - [LangGraph state checkpoints](/use-cases/langgraph-state-checkpoints) — framework-level version of the same crash-resumable pattern --- URL: /use-cases/full-dev-backend-in-one-curl.md --- --- title: Full dev backend in one curl category: F. Developer tooling services: ["pg", "redis", "mongo"] scenario: An AI agent or developer provisions Postgres + Redis + MongoDB anonymously to develop against — no Docker, no cloud account, no installer — and tears it down when done. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an AI agent or developer provisions Postgres + Redis + MongoDB anonymously to develop against — no Docker, no cloud account, no installer — and tears it down when done. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + Redis + MongoDB) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Give me a full dev backend in one go. Claim Postgres, Redis, and MongoDB on instanode.dev anonymously. Export connection URLs as env vars. Run my app against them. When I'm done, DELETE all three. ``` ## Steps to follow - **Step 1: Three curls in parallel.** Anonymous, no signup, all return in under a second. ```bash H='Content-Type: application/json' export PG_URL=$(curl -sX POST https://api.instanode.dev/db/new -H "$H" -d '{"name":"dev-postgres"}' | jq -r .connection_url) export REDIS_URL=$(curl -sX POST https://api.instanode.dev/cache/new -H "$H" -d '{"name":"dev-cache"}' | jq -r .connection_url) export MONGO_URL=$(curl -sX POST https://api.instanode.dev/nosql/new -H "$H" -d '{"name":"dev-mongo"}' | jq -r .connection_url) ``` - **Step 2: Run your app.** Reads env vars; no other setup. ```bash npm run dev ``` - **Step 3: Verify all three are reachable.** Sanity ping from the shell. ```bash psql $PG_URL -c 'SELECT 1' redis-cli -u $REDIS_URL PING mongosh "$MONGO_URL" --eval 'db.runCommand({ping:1})' ``` - **Step 4: Nothing to tear down.** These three resources are provisioned anonymously, so they auto-reap at the 24h TTL — a forgotten backend has bounded blast radius and costs nothing. If you later claim them (and hold a session token), you can delete any resource early with `DELETE /api/v1/resources/:id`. ## Why this works on instanode.dev This is the canonical instanode flow: no Docker daemon, no `docker compose up`, no port collisions, no localhost binds. The same URLs work from your laptop, a teammate's laptop, a CI runner, or a deployed container — because they're public endpoints with token auth. Three real production-grade services in three seconds, zero setup, zero account. ## Related cases - [24-hour hackathon backend](/use-cases/24-hour-hackathon-backend) — hackathon-flavored variant of the same anonymous-bundle idea - [One-afternoon MVP backend](/use-cases/one-afternoon-mvp-backend) — paid-tier extension that adds deploy on top - [Agent-resilience chaos lab](/use-cases/agent-resilience-chaos-lab) — same bundle plus chaos injection for resilience testing --- URL: /use-cases/gaia-tournament-bracket.md --- --- title: GAIA tournament bracket category: P. Agent benchmarking & evaluation services: ["mongo", "storage", "redis"] scenario: A tournament service runs 16 agent variants head-to-head on GAIA tasks; pairings live in Mongo, intermediate transcripts in S3-compatible storage, win counts in Redis sorted sets for the live leaderboard. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a tournament service runs 16 agent variants head-to-head on GAIA tasks; pairings live in Mongo, intermediate transcripts in S3-compatible storage, win counts in Redis sorted sets for the live leaderboard. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (MongoDB + S3-compatible storage + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Run a 16-agent GAIA tournament. Claim Mongo + S3-compatible storage + Redis on instanode.dev. Pairings + per-task outcomes in Mongo. Full per-task transcripts in S3-compatible storage. Live leaderboard win counts in Redis sorted set. After every match, update all three. ``` ## Steps to follow - **Step 1: Provision all three stores.** Tournament infra in 3 curls. ```bash MONGO=$(curl -sX POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"gaia-tournament-bracket-mongo"}' | jq -r .connection_url) S3=$(curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"gaia-tournament-bracket-storage"}') REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"gaia-tournament-bracket-cache"}' | jq -r .connection_url) ``` - **Step 2: Define bracket.** 16 agents → 8 matches round 1. ```python pairings = [{"round":1,"match":i,"a":agents[2*i],"b":agents[2*i+1]} for i in range(8)] mongo.pairings.insert_many(pairings) ``` - **Step 3: Run a match.** Both agents answer the same GAIA task; transcripts to S3, score to Mongo + Redis. ```python for p in pairings: a_ans, a_trace = run_agent(p["a"], task) b_ans, b_trace = run_agent(p["b"], task) winner = judge(task, a_ans, b_ans) s3.put_object(Bucket=bucket, Key=f"r{p['round']}/m{p['match']}/{p['a']}.json", Body=json.dumps(a_trace)) s3.put_object(Bucket=bucket, Key=f"r{p['round']}/m{p['match']}/{p['b']}.json", Body=json.dumps(b_trace)) mongo.pairings.update_one({"_id":p["_id"]}, {"$set":{"winner":winner}}) r.zincrby("leaderboard", 1, winner) ``` - **Step 4: Live leaderboard.** Sub-millisecond reads. ```bash redis-cli -u $REDIS_URL ZREVRANGE leaderboard 0 -1 WITHSCORES ``` ## Why this works on instanode.dev Each service maps to exactly its strength: Mongo's flexible schema for bracket structure, S3-compatible storage for fat transcripts (avg ~2MB), Redis sorted sets for the live leaderboard. Provisioning all three with the same anonymous token means the tournament runner has no IAM glue to write. If a result is contested, the object in S3-compatible storage is the source of truth — replay it deterministically. ## Related cases - [SWE-bench parallel rollout harness](/use-cases/swe-bench-parallel-rollout-harness) — code-eval cousin that scales to 500 isolated tasks - [LLM-as-judge consensus pool](/use-cases/llm-as-judge-consensus-pool) — judge layer that picks winners between bracket pairs - [Adversarial red-team runner](/use-cases/adversarial-red-team-runner) — parallel-attacker variant of the same eval-fleet pattern --- URL: /use-cases/geo-sharded-chat-agent-fleet.md --- --- title: Geo-sharded chat-agent fleet category: R. Edge agents & federated swarms services: ["redis", "pg"] scenario: Region-pinned agents in EU, US, and APAC each own a local Redis for session state, replicating only consented memories to a central Postgres for cross-region handoff. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: region-pinned agents in EU, US, and APAC each own a local Redis for session state, replicating only consented memories to a central Postgres for cross-region handoff. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Redis + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build a geo-sharded chat fleet. In each region (US/EU/APAC), claim a local Redis on instanode.dev for session state. Claim one shared Postgres for consented cross-region memories. Region pin agents by edge location; only "memorable" messages (user opt-in) replicate to Postgres. ``` ## Steps to follow - **Step 1: Provision per-region Redis.** Use region hint on the request. ```bash for r in us-east eu-west ap-south; do curl -sX POST https://api.instanode.dev/cache/new \ -H "Content-Type: application/json" -d "{\"name\":\"geo-sharded-chat-agent-fleet-cache\",\"region\":\"$r\"}" \ | jq -r .connection_url > redis-$r.url done PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"geo-sharded-chat-agent-fleet-db"}' | jq -r .connection_url) ``` - **Step 2: Session state writes locally.** Edge agent reads its REDIS_URL env var. ```python r = redis.from_url(os.environ["REDIS_URL"]) r.hset(f"session:{user_id}", mapping={"last_msg": msg, "ts": time.time()}) ``` - **Step 3: Memorable messages replicate.** Gated by user opt-in flag. ```python if user_opted_in_memory: pg.execute("INSERT INTO memories(user_id, region, content, embedding) VALUES (%s,%s,%s,%s)", (user_id, region, msg, embed)) ``` - **Step 4: Cross-region handoff.** Roaming user reads from central Postgres on new region's Redis miss. ```python state = r.hgetall(f"session:{user_id}") if not state: mems = pg.execute("SELECT content FROM memories WHERE user_id=%s ORDER BY ts DESC LIMIT 20", (user_id,)) r.hset(f"session:{user_id}", "warm", json.dumps(mems)) ``` ## Why this works on instanode.dev Region-pinned Redis keeps per-session reads on the same continent as the user — chat latency stays under 50ms. The shared Postgres carries only consented, dense memories, so cross-region replication bandwidth is bounded by user choice, not by chat volume. One control plane for all four resources; one token model; no AWS region toggling, no Aurora Global setup. ## Related cases - [Per-device edge-agent state sync](/use-cases/per-device-edge-agent-state-sync) — device-scale variant of the same regional-sync pattern - [Federated-learning aggregator](/use-cases/federated-learning-aggregator) — another partial-state-leaves-the-edge replication shape - [Cross-device chat history](/use-cases/cross-device-chat-history) — the single-user equivalent of regional chat agents --- URL: /use-cases/high-volume-pr-review-pipeline.md --- --- title: High-volume PR-review pipeline category: F. Developer tooling services: ["nats", "storage"] scenario: An automated reviewer handles thousands of MRs/day, queues each review job, and stores comment artifacts per run. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an automated reviewer handles thousands of MRs/day, queues each review job, and stores comment artifacts per run. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream + S3-compatible storage) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Set up the backend for our AI PR-review bot that handles 3k MRs/day. Provision a NATS JetStream queue for review jobs and a S3-compatible bucket for the markdown comment artifacts each run produces. Wire a small Go publisher that enqueues one job per merge_request.open webhook and a worker that reads from the stream, runs the review, and uploads the artifact. Return the connection URLs once both resources are live. ``` ## Steps to follow - **Step 1: Provision the JetStream queue.** One curl gets you a durable NATS URL with a stream pre-created. ```bash curl -s -X POST https://api.instanode.dev/queue/new \ -H 'Content-Type: application/json' \ -d '{"name":"high-volume-pr-review-pipeline-queue","stream":"pr-reviews","subjects":["review.>"]}' | jq . ``` - **Step 2: Provision the artifact bucket.** A scoped S3-compatible bucket for per-MR markdown. ```bash curl -s -X POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"high-volume-pr-review-pipeline-storage"}' | jq -r .connection_url ``` - **Step 3: Publish a job on each GitLab webhook.** ```python import nats, json nc = await nats.connect(os.environ["NATS_URL"]) js = nc.jetstream() await js.publish("review.queued", json.dumps({"mr_id": mr, "sha": sha}).encode()) ``` - **Step 4: Pull-consumer in the worker.** Acks only on successful upload to S3-compatible storage. ```python sub = await js.pull_subscribe("review.queued", durable="reviewer") msgs = await sub.fetch(8, timeout=5) ``` - **Step 5: Upload the markdown comment file with the MR id as the key.** ```bash aws --endpoint-url "$MINIO_ENDPOINT" s3 cp review.md s3://artifacts/mr-$MR_ID.md ``` ## Why this works on instanode.dev JetStream gives you at-least-once delivery and durable consumers without standing up a broker, and S3-compatible storage is wire-compatible with the AWS CLI you already use. Both resources are claimed under the same token, so when traffic grows past the hobby tier you upgrade once and every consumer keeps its URL. ## Related cases - [Devin-style PR-bot fleet](/use-cases/devin-style-pr-bot-fleet) — per-issue ephemeral-worker shape of the same review fleet - [CI flake-tracker](/use-cases/ci-flake-tracker) — consumes the same CI webhook stream this pipeline reviews - [PR-review bot triggered by webhooks](/use-cases/pr-review-bot-triggered-by-webhooks) — single-bot version of this thousands-of-PRs pipeline --- URL: /use-cases/inbox-zero-agent-fleet.md --- --- title: Inbox-zero agent fleet category: Q. Background/async agent fleets services: ["storage", "pg", "webhook"] scenario: A Cloudflare-Email-style fleet runs one durable agent per user that triages incoming email, files attachments in S3-compatible storage, and stores extracted action items in Postgres. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Cloudflare-Email-style fleet runs one durable agent per user that triages incoming email, files attachments in S3-compatible storage, and stores extracted action items in Postgres. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (S3-compatible storage + Postgres + webhook receiver) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build a per-user durable email-triage agent. For each user, provision a S3-compatible bucket for attachments, a Postgres row-store for extracted action items, and a webhook endpoint that Cloudflare Email Workers will POST inbound messages to. Each agent should classify, file attachments, and persist next-actions. Return the three URLs and the user-id mapping. ``` ## Steps to follow - **Step 1: Provision the Postgres for action items.** ```bash curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"inbox-zero-agent-fleet-db"}' | tee /tmp/pg.json ``` - **Step 2: Provision the attachment bucket.** ```bash curl -s -X POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"inbox-zero-agent-fleet-storage"}' | tee /tmp/s3.json ``` - **Step 3: Provision an inbound-email webhook receiver.** ```bash curl -s -X POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"inbox-zero-agent-fleet-webhook"}' | tee /tmp/wh.json ``` - **Step 4: Create the action-items schema.** ```sql CREATE TABLE actions ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id text NOT NULL, message_id text NOT NULL, due_at timestamptz, body text, created_at timestamptz DEFAULT now() ); CREATE INDEX ON actions (user_id, due_at); ``` - **Step 5: Worker reads inbound webhook batches.** ```python inbound = requests.get(f"{WH_URL}/requests?since={cursor}").json() for msg in inbound: items = triage_agent.run(msg["body"]) pg.executemany("INSERT INTO actions(...) VALUES (...)", items) for att in msg["attachments"]: s3.put_object(Bucket="inbox", Key=f"{user}/{att['name']}", Body=att["bytes"]) ``` ## Why this works on instanode.dev The webhook receiver buffers inbound mail for you, so the triage agent can fall behind during a spike without losing messages. Postgres and S3-compatible storage live under the same token, which means one billing relationship and one upgrade path when a user's fleet grows past the hobby quota. ## Related cases - [Slack/Discord async bot factory](/use-cases/slack-discord-async-bot-factory) — chat-platform sibling of this per-user durable-agent pattern - [Overnight dossier fleet](/use-cases/overnight-dossier-fleet) — another async fleet writing Mongo + S3-compatible storage artifacts - [Per-tenant chatbot factory at signup](/use-cases/per-tenant-chatbot-factory-at-signup) — tenant-spawning variant of the same per-user idea --- URL: /use-cases/langgraph-fan-out-research-agents.md --- --- title: LangGraph fan-out research agents category: J. Agent swarms & fan-out services: ["nats", "pg"] scenario: A planner agent splits a research question into 12 sub-queries and dispatches them to parallel LangGraph workers that each hit different sources, returning JSON to a NATS subject the reducer subscribes to. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a planner agent splits a research question into 12 sub-queries and dispatches them to parallel LangGraph workers that each hit different sources, returning JSON to a NATS subject the reducer subscribes to. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` I need to write a literature review on "GLP-1 receptor agonists and cardiovascular outcomes in non-diabetic patients" by tomorrow morning. Build me a LangGraph planner that decomposes the question into 12 sub-queries (mechanism, RCT evidence, observational data, MACE endpoints, side effects, cost-effectiveness, guideline positions, etc.), fans them out as NATS JetStream messages on `research.work.`, and runs 12 parallel workers that each query PubMed + Semantic Scholar + a web search and write their raw findings (with citations) to a Postgres `findings` table. The reducer subscribes to `research.done.`, collects all 12 results, and synthesizes a 1500-word draft with inline citations. Provision NATS + Postgres on instanode.dev and print the URLs. ``` ## Steps to follow We'll thread one query — the GLP-1 literature review above — through every step. By the end you'll have 12 worker results in Postgres and a synthesized draft in stdout. - **Step 1: Provision NATS JetStream + Postgres in two POSTs.** The same claimed token owns both; workers receive both URLs as env. ```bash NATS=$(curl -sX POST https://api.instanode.dev/queue/new \ -H 'Content-Type: application/json' \ -d '{"name":"langgraph-fan-out-research-agents-queue","stream":"research","subjects":["research.work.*","research.done.*"]}' \ | jq -r .nats_url) PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"langgraph-fan-out-research-agents-db"}' | jq -r .connection_url) printf "NATS_URL=%s\nPG_URL=%s\n" "$NATS" "$PG" > .env ``` - **Step 2: Persistence schema for the findings.** A composite primary key on `(run_id, sub_query)` makes idempotent re-deliveries safe. ```sql CREATE TABLE findings ( run_id uuid NOT NULL, sub_query text NOT NULL, sources jsonb NOT NULL, summary text NOT NULL, received_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (run_id, sub_query) ); CREATE INDEX findings_by_run ON findings(run_id); ``` - **Step 3: The planner LangGraph node.** Decomposes the question with the LLM, publishes 12 messages onto `research.work.`. Each message carries the sub-query and the run_id so workers and the reducer share the same correlation key. ```python # graph/planner.py import json, uuid, nats from nats.js import JetStreamContext PROMPT = """Decompose this medical literature question into exactly 12 non-overlapping sub-queries that together cover the topic. Return JSON list of strings. Question: {q}""" async def planner(state): run_id = str(uuid.uuid4()) sub_queries = await llm_json(PROMPT.format(q=state["question"])) assert len(sub_queries) == 12, f"expected 12, got {len(sub_queries)}" nc = await nats.connect(os.environ["NATS_URL"]) js: JetStreamContext = nc.jetstream() for sq in sub_queries: await js.publish( f"research.work.{run_id}", json.dumps({"q": sq, "run": run_id}).encode(), ) return {**state, "run_id": run_id, "sub_queries": sub_queries} ``` - **Step 4: Workers — 12 of them, durably subscribed.** A durable consumer means a crashed worker's message redelivers to a sibling; JetStream's per-subject filter keeps concurrent research runs isolated. ```python # graph/worker.py async def worker(): nc = await nats.connect(os.environ["NATS_URL"]) js = nc.jetstream() sub = await js.subscribe("research.work.*", durable="workers", manual_ack=True) async for msg in sub.messages: payload = json.loads(msg.data) run_id, q = payload["run"], payload["q"] sources = await fetch_sources(q) # pubmed + semscholar + web summary = await llm_summarize(q, sources) with psycopg.connect(os.environ["PG_URL"]) as cn: cn.execute( "INSERT INTO findings (run_id, sub_query, sources, summary) " "VALUES (%s, %s, %s, %s) " "ON CONFLICT (run_id, sub_query) DO NOTHING", (run_id, q, json.dumps(sources), summary), ) await js.publish(f"research.done.{run_id}", json.dumps({"q": q, "summary": summary}).encode()) await msg.ack() ``` - **Step 5: Reducer waits for 12 done-messages, scoped to this run.** The per-subject filter (`research.done.`) is what lets ten concurrent research runs share one JetStream without cross-talk. ```python async def reducer(state): run_id = state["run_id"] nc = await nats.connect(os.environ["NATS_URL"]) js = nc.jetstream() sub = await js.subscribe(f"research.done.{run_id}") collected = [] for _ in range(12): msg = await sub.next_msg(timeout=120) collected.append(json.loads(msg.data)) draft = await llm_synthesize(state["question"], collected) return {**state, "draft": draft} ``` - **Step 6: Run end-to-end and verify.** Twelve rows land in Postgres, the reducer emits the synthesized draft. ```bash python -m graph.run --question "GLP-1 receptor agonists and cardiovascular outcomes in non-diabetic patients" psql "$PG_URL" -c "SELECT count(*) FROM findings WHERE run_id = (SELECT run_id FROM findings ORDER BY received_at DESC LIMIT 1);" # count # ------- # 12 ``` ## Why this works on instanode.dev Fan-out research swarms have historically been gated by two costs that look small individually and ruin the pattern in aggregate. The **broker problem**: NATS, RabbitMQ, or Kafka all want a config file, a TLS cert, and a port reachable from every worker — fine for one team, fatal when the agent itself wants to spin up the topology on demand. **CloudAMQP** and **Upstash Kafka** solve provisioning but cost real money per durable consumer and gate creation behind an account. The **persistence problem**: pairing the queue with a results store usually means a second signup (Supabase, Render, RDS) and a second secret to plumb into every worker. instanode hands the planner, all 12 workers, and the reducer one claimed token that owns a real NATS JetStream URL with subject filtering and a Postgres for findings — both reachable over the public internet, both provisioned in two POSTs. The per-subject filter (`research.done.`) means you can run ten of these concurrently in the same stream without correlation-id juggling, and durable consumers mean a worker crash redelivers rather than drops. ## Related cases - [CrewAI parallel-process crew](/use-cases/crewai-parallel-process-crew) — framework-equivalent parallel-research pattern - [Magentic-One DAG executor](/use-cases/magentic-one-dag-executor) — explicit DAG version of fan-out research - [Scatter-gather price comparison swarm](/use-cases/scatter-gather-price-comparison-swarm) — first-N-wins variant of the same fan-out idea --- URL: /use-cases/langgraph-state-checkpoints.md --- --- title: LangGraph state checkpoints category: B. Multi-agent systems services: ["pg"] scenario: A LangGraph workflow checkpoints node state to Postgres so a crashed run resumes mid-graph instead of restarting from scratch. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a LangGraph workflow checkpoints node state to Postgres so a crashed run resumes mid-graph instead of restarting from scratch. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Wire LangGraph's PostgresSaver checkpointer so our research workflow survives crashes. Provision Postgres on instanode, install the checkpointer schema, and configure the graph to save state after every node. Verify by killing the process mid-run and resuming from the same thread_id. ``` ## Steps to follow - **Step 1: Provision Postgres.** ```bash curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"langgraph-state-checkpoints-db"}' | jq -r .connection_url > .pg ``` - **Step 2: Install the checkpointer schema.** ```python from langgraph.checkpoint.postgres import PostgresSaver saver = PostgresSaver.from_conn_string(open(".pg").read().strip()) saver.setup() ``` - **Step 3: Compile the graph with the checkpointer.** ```python graph = builder.compile(checkpointer=saver) cfg = {"configurable": {"thread_id": "research-2026-05-11-a"}} graph.invoke({"question": q}, cfg) ``` - **Step 4: Crash test.** ```bash # Kill the worker mid-node, then resume: python run.py --thread research-2026-05-11-a --resume ``` - **Step 5: Inspect the checkpoint trail.** ```sql SELECT thread_id, checkpoint_id, step, jsonb_path_query(checkpoint, '$.channel_values.messages') FROM checkpoints WHERE thread_id = 'research-2026-05-11-a' ORDER BY step; ``` ## Why this works on instanode.dev LangGraph's PostgresSaver only needs a working DSN, which the `/db/new` response gives you in one call. There is no separate checkpoint service to run, and the same DB row-stores your run history, so debugging a stuck thread is one SQL query away. ## Related cases - [Form-fill state machine](/use-cases/form-fill-state-machine) — domain-specific instance of the same crash-resume pattern - [Restate-style durable sidecar](/use-cases/restate-style-durable-sidecar) — out-of-process alternative to in-graph checkpoints - [Long-horizon Temporal agent workflow](/use-cases/long-horizon-temporal-agent-workflow) — scales the checkpoint idea to 14-day workflows --- URL: /use-cases/live-agent-status-broadcast.md --- --- title: Live agent status broadcast category: B. Multi-agent systems services: ["nats", "redis"] scenario: Worker agents broadcast heartbeats on a status subject so a dashboard shows which agent is stuck mid-tool-call. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: worker agents broadcast heartbeats on a status subject so a dashboard shows which agent is stuck mid-tool-call. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build a heartbeat fabric for our worker swarm. Each agent publishes a status heartbeat to NATS every 2s with current tool call and last token timestamp. A dashboard subscriber updates Redis keys per agent with a 10s TTL so the UI shows red on any agent missing two beats. Provision NATS and Redis and wire both sides. ``` ## Steps to follow - **Step 1: Provision NATS and Redis.** ```bash curl -s -X POST https://api.instanode.dev/queue/new -d '{"name":"live-agent-status-broadcast-queue","stream":"status"}' -H 'Content-Type: application/json' curl -s -X POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"live-agent-status-broadcast-cache"}' ``` - **Step 2: Heartbeat publisher inside each agent.** ```python async def heartbeat(agent_id, current_tool): await nc.publish(f"agents.heartbeat.{agent_id}", json.dumps({"tool": current_tool, "ts": time.time()}).encode()) ``` - **Step 3: Subscriber writes to Redis with a 10s expiry.** ```python async def handler(msg): agent = msg.subject.split(".")[-1] await redis.set(f"agent:{agent}:status", msg.data, ex=10) await nc.subscribe("agents.heartbeat.*", cb=handler) ``` - **Step 4: Dashboard query for live status.** ```python keys = await redis.keys("agent:*:status") live = {k.decode(): json.loads(await redis.get(k)) for k in keys} ``` - **Step 5: Stale detector loop.** ```bash redis-cli --scan --pattern 'agent:*:status' | while read k; do redis-cli ttl "$k" | awk -v k="$k" '$1 < 5 {print k " stale"}' done ``` ## Why this works on instanode.dev NATS fanout is sub-millisecond, so the dashboard reflects the swarm in real time even at thousands of agents. Redis TTLs do the "is it alive" check for free, and both resources sit behind one token so the heartbeat fabric is provisioned in two curls. ## Related cases - [Live agent-topology graph](/use-cases/live-agent-topology-graph) — consumes these heartbeats to draw the parent/child graph - [Deploy-status MCP server](/use-cases/deploy-status-mcp-server) — broadcast-via-NATS pattern, applied to deploys instead of agents - [Per-agent dead-letter inspection queue](/use-cases/per-agent-dead-letter-inspection-queue) — complementary failure-side view of the same swarm --- URL: /use-cases/live-agent-topology-graph.md --- --- title: Live agent-topology graph category: N. Multi-agent observability services: ["nats", "pg"] scenario: Each spawn/handoff event is published to a NATS subject; a topology agent subscribes and maintains a real-time graph of which parent spawned which child in Postgres for the dashboard. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: each spawn/handoff event is published to a NATS subject; a topology agent subscribes and maintains a real-time graph of which parent spawned which child in Postgres for the dashboard. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build a live topology graph of our agent fleet. Every spawn or handoff publishes an event to NATS with parent_id and child_id. A topology agent subscribes, upserts edges into Postgres, and exposes a query for the React dashboard to render the live tree. Provision NATS and Postgres and return URLs. ``` ## Steps to follow - **Step 1: Provision NATS and Postgres.** ```bash curl -s -X POST https://api.instanode.dev/queue/new -d '{"name":"live-agent-topology-graph-queue","stream":"topo"}' -H 'Content-Type: application/json' curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"live-agent-topology-graph-db"}' ``` - **Step 2: Edge schema.** ```sql CREATE TABLE agent_edges ( parent_id text NOT NULL, child_id text NOT NULL, kind text NOT NULL, created_at timestamptz DEFAULT now(), PRIMARY KEY (parent_id, child_id) ); CREATE INDEX ON agent_edges (parent_id); ``` - **Step 3: Publish spawn/handoff from each agent.** ```python await nc.publish("topo.event", json.dumps({"parent": parent, "child": child, "kind": "spawn"}).encode()) ``` - **Step 4: Topology subscriber upserts edges.** ```python async def on_event(msg): e = json.loads(msg.data) pg.execute("""INSERT INTO agent_edges VALUES (%s,%s,%s) ON CONFLICT DO NOTHING""", e["parent"], e["child"], e["kind"]) await nc.subscribe("topo.event", cb=on_event) ``` - **Step 5: Recursive query for the dashboard tree.** ```sql WITH RECURSIVE tree AS ( SELECT parent_id, child_id, 0 AS depth FROM agent_edges WHERE parent_id = $1 UNION ALL SELECT e.parent_id, e.child_id, t.depth+1 FROM agent_edges e JOIN tree t ON e.parent_id = t.child_id ) SELECT * FROM tree; ``` ## Why this works on instanode.dev NATS gives the swarm a single event bus that any spawning library can publish to with one line. Postgres' recursive CTEs render the tree without an extra graph DB, and both resources live under one token so the topology service deploys with two curls. ## Related cases - [Live agent status broadcast](/use-cases/live-agent-status-broadcast) — the heartbeat source this topology graph subscribes to - [Agent-run lineage store](/use-cases/agent-run-lineage-store) — persistent-history counterpart to the live spawn graph - [OpenTelemetry agent-trace ingest](/use-cases/opentelemetry-agent-trace-ingest) — OTel-spans variant of the same span/edge ingestion --- URL: /use-cases/llm-as-judge-consensus-pool.md --- --- title: LLM-as-judge consensus pool category: P. Agent benchmarking & evaluation services: ["pg", "nats"] scenario: Five judge agents score the same agent output in parallel; their verdicts converge in Postgres and a tiebreaker rolls in only on disagreement, all coordinated through a NATS request/reply. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: five judge agents score the same agent output in parallel; their verdicts converge in Postgres and a tiebreaker rolls in only on disagreement, all coordinated through a NATS request/reply. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + NATS JetStream) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build a five-judge consensus pool. Each judge agent subscribes to a NATS request subject, scores the candidate output 1-5, and replies. A coordinator collects all five verdicts, writes them to Postgres, and only spawns a tiebreaker if the variance exceeds 1.5. Provision NATS and Postgres. ``` ## Steps to follow - **Step 1: Provision the resources.** ```bash curl -s -X POST https://api.instanode.dev/queue/new -d '{"name":"llm-as-judge-consensus-pool-queue","stream":"judges"}' -H 'Content-Type: application/json' curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"llm-as-judge-consensus-pool-db"}' ``` - **Step 2: Verdict schema.** ```sql CREATE TABLE verdicts ( eval_id uuid NOT NULL, judge text NOT NULL, score int NOT NULL, rationale text, created_at timestamptz DEFAULT now(), PRIMARY KEY (eval_id, judge) ); ``` - **Step 3: Five judges, each subscribed with a queue group.** ```python await nc.subscribe("judge.eval", queue="judge-pool", cb=score_handler) # request/reply: coordinator publishes 5 times, gets 5 replies ``` - **Step 4: Coordinator fans out and collects.** ```python results = await asyncio.gather(*[ nc.request("judge.eval", payload, timeout=10) for _ in range(5) ]) for r in results: pg.execute("INSERT INTO verdicts VALUES (%s,%s,%s,%s)", eval_id, r.judge, r.score, r.why) ``` - **Step 5: Tiebreaker only on disagreement.** ```sql SELECT eval_id, stddev(score) AS spread FROM verdicts GROUP BY eval_id HAVING stddev(score) > 1.5; ``` ## Why this works on instanode.dev NATS request/reply with a queue group load-balances across judges without you writing a router, and Postgres gives you the analytical layer for spread analysis in the same store. One token, two curls, full consensus pool. ## Related cases - [Adversarial red-team runner](/use-cases/adversarial-red-team-runner) — complementary parallel-evaluators pattern from the attacker side - [GAIA tournament bracket](/use-cases/gaia-tournament-bracket) — judges plug into this bracket as the pairing arbiter - [Multi-model bake-off router](/use-cases/multi-model-bake-off-router) — race-and-pick alternative that doesn't bother with consensus --- URL: /use-cases/long-horizon-temporal-agent-workflow.md --- --- title: Long-horizon Temporal agent workflow category: Q. Background/async agent fleets services: ["pg", "nats"] scenario: A Temporal-backed agent runs a 14-day procurement negotiation across vendors; each step persists in Postgres with NATS signals so a human can interject without breaking the workflow. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Temporal-backed agent runs a 14-day procurement negotiation across vendors; each step persists in Postgres with NATS signals so a human can interject without breaking the workflow. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + NATS JetStream) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Set up a Temporal-backed 14-day procurement negotiation agent. Each negotiation step persists to Postgres and emits a NATS signal so a human can intervene. Provision Postgres for negotiation state and NATS for signal delivery, then return URLs we wire into the Temporal worker. ``` ## Steps to follow - **Step 1: Provision the persistent state store and signal bus.** ```bash curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"long-horizon-temporal-agent-workfl-db"}' curl -s -X POST https://api.instanode.dev/queue/new -d '{"name":"long-horizon-temporal-agent-workfl-queue","stream":"procurement"}' -H 'Content-Type: application/json' ``` - **Step 2: Negotiation state schema.** ```sql CREATE TABLE negotiation_steps ( workflow_id text NOT NULL, step int NOT NULL, vendor text, offer numeric, counter numeric, decided_at timestamptz, PRIMARY KEY (workflow_id, step) ); ``` - **Step 3: Temporal activity persists each step.** ```python @activity.defn async def record_offer(wf_id, step, vendor, offer): pg.execute("INSERT INTO negotiation_steps(workflow_id,step,vendor,offer) VALUES (%s,%s,%s,%s)", wf_id, step, vendor, offer) await nc.publish("procurement.offer", json.dumps({"wf": wf_id, "offer": offer}).encode()) ``` - **Step 4: Human-interject signal handler in the workflow.** ```python @workflow.signal async def human_override(self, new_terms): self.terms = new_terms ``` - **Step 5: Operator UI publishes an override via NATS, which the worker translates to a Temporal signal.** ```bash nats pub procurement.override '{"wf":"proc-42","floor":18000}' ``` ## Why this works on instanode.dev Temporal handles the 14-day timer; Postgres holds the negotiation audit trail; NATS carries human interjections. All three are provisioned in two curls, and the same Postgres can host Temporal's persistence backend if you want to consolidate further. ## Related cases - [Restate-style durable sidecar](/use-cases/restate-style-durable-sidecar) — lighter-weight durability sidecar without a Temporal engine - [LangGraph state checkpoints](/use-cases/langgraph-state-checkpoints) — in-process checkpoint version of the same resume idea - [Magentic-One DAG executor](/use-cases/magentic-one-dag-executor) — DAG-shaped orchestration over a shorter horizon --- URL: /use-cases/magentic-one-dag-executor.md --- --- title: Magentic-One DAG executor category: J. Agent swarms & fan-out services: ["nats", "pg"] scenario: A Microsoft-Magentic-One-style orchestrator decomposes a goal into a task DAG, dispatches independent branches to parallel agents, and merges their outputs after a quality-gate agent approves each branch. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Microsoft-Magentic-One-style orchestrator decomposes a goal into a task DAG, dispatches independent branches to parallel agents, and merges their outputs after a quality-gate agent approves each branch. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Implement a Magentic-One-style orchestrator: decompose a goal into a DAG of tasks, dispatch independent branches to worker agents via NATS, and merge their outputs after a quality-gate agent approves each branch. Provision NATS for task dispatch and Postgres to hold the DAG and branch outputs. ``` ## Steps to follow - **Step 1: Provision queue and DB.** ```bash curl -s -X POST https://api.instanode.dev/queue/new -d '{"name":"magentic-one-dag-executor-queue","stream":"dag"}' -H 'Content-Type: application/json' curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"magentic-one-dag-executor-db"}' ``` - **Step 2: DAG and outputs schema.** ```sql CREATE TABLE tasks ( run_id uuid, task_id text, depends_on text[], status text DEFAULT 'pending', output jsonb, gate_passed boolean, PRIMARY KEY (run_id, task_id) ); ``` - **Step 3: Orchestrator dispatches ready tasks.** ```python ready = pg.fetch(""" SELECT task_id FROM tasks WHERE run_id=$1 AND status='pending' AND NOT EXISTS (SELECT 1 FROM unnest(depends_on) d JOIN tasks t ON t.task_id=d WHERE t.status<>'gated_ok')""", run) for t in ready: await js.publish(f"dag.work.{t['task_id']}", json.dumps({...}).encode()) ``` - **Step 4: Workers complete and push to a quality gate.** ```python async def worker(msg): out = run_agent(msg) pg.execute("UPDATE tasks SET output=$1, status='gating' WHERE task_id=$2", out, msg["task"]) await js.publish("dag.gate", json.dumps({"task": msg["task"]}).encode()) ``` - **Step 5: Gate agent approves or rejects.** ```python verdict = gate_llm.judge(output) pg.execute("UPDATE tasks SET gate_passed=$1, status=$2 WHERE task_id=$3", verdict.ok, "gated_ok" if verdict.ok else "rejected", task) ``` ## Why this works on instanode.dev The DAG state lives in Postgres so the orchestrator restarts cleanly, and NATS subjects let independent branches run truly in parallel without a workflow engine. One claimed token, two curls, and the gating loop is queryable SQL. ## Related cases - [LangGraph fan-out research agents](/use-cases/langgraph-fan-out-research-agents) — framework-specific fan-out without an explicit DAG - [CrewAI parallel-process crew](/use-cases/crewai-parallel-process-crew) — CrewAI-flavored parallel orchestration - [Long-horizon Temporal agent workflow](/use-cases/long-horizon-temporal-agent-workflow) — Temporal-backed long-running variant of DAG execution --- URL: /use-cases/multi-model-bake-off-router.md --- --- title: Multi-model bake-off router category: M. Parallel tool execution services: ["redis", "nats"] scenario: A router agent dispatches the same prompt to GPT, Claude, and Gemini concurrently; the first valid JSON response wins, and loser turns get cached in Redis for next time. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a router agent dispatches the same prompt to GPT, Claude, and Gemini concurrently; the first valid JSON response wins, and loser turns get cached in Redis for next time. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Redis + NATS JetStream) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build a model bake-off router. The router publishes the same prompt to GPT, Claude, and Gemini concurrently on NATS subjects, the first valid JSON reply wins, and the slower replies get cached in Redis so we never re-run them for the same prompt hash. Provision NATS and Redis. ``` ## Steps to follow - **Step 1: Provision the bus and cache.** ```bash curl -s -X POST https://api.instanode.dev/queue/new -d '{"name":"multi-model-bake-off-router-queue","stream":"bakeoff"}' -H 'Content-Type: application/json' curl -s -X POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"multi-model-bake-off-router-cache"}' ``` - **Step 2: Three model workers, queue-grouped by model name.** ```python await nc.subscribe("bakeoff.gpt", queue="gpt", cb=run_gpt) await nc.subscribe("bakeoff.claude", queue="claude", cb=run_claude) await nc.subscribe("bakeoff.gemini", queue="gemini", cb=run_gemini) ``` - **Step 3: Router fans out and races.** ```python inflight = [ asyncio.create_task(nc.request(f"bakeoff.{m}", payload, timeout=15)) for m in ("gpt", "claude", "gemini") ] done, pending = await asyncio.wait(inflight, return_when=asyncio.FIRST_COMPLETED) winner = next(iter(done)).result() ``` - **Step 4: Loser replies finish in the background, cached by prompt hash.** ```python async def stash(task, model): try: r = await task await redis.setex(f"cache:{model}:{prompt_hash}", 86400, r.data) except: pass for t, m in zip(pending, ("claude", "gemini")): asyncio.create_task(stash(t, m)) ``` - **Step 5: Next time, peek the cache before dispatching.** ```python hit = await redis.get(f"cache:claude:{prompt_hash}") if hit: return json.loads(hit) ``` ## Why this works on instanode.dev NATS' first-reply-wins pattern falls out of the request/wait primitive without extra plumbing, and Redis keeps the "wasted" generations productive by feeding the next request. Both resources are one curl each. ## Related cases - [Anthropic parallel tool_use batch](/use-cases/anthropic-parallel-tool-use-batch) — same race-and-collect shape, but across tools instead of models - [Speculative agent rollout race](/use-cases/speculative-agent-rollout-race) — races temperatures of one model instead of three providers - [LLM-as-judge consensus pool](/use-cases/llm-as-judge-consensus-pool) — judge variant when you want consensus instead of first-to-win --- URL: /use-cases/multi-repo-shared-scratchpad.md --- --- title: Multi-repo shared scratchpad category: A. AI coding agents services: ["mongo"] scenario: Multiple agents working across separate repos coordinate via a shared scratchpad document store keyed by feature branch. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: multiple agents working across separate repos coordinate via a shared scratchpad document store keyed by feature branch. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (MongoDB) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Spin up a shared Mongo scratchpad so the four coding agents working across our monorepo + two satellite repos can leave notes for each other, keyed by feature branch. The schema is flexible (each note is a JSON doc). Provision Mongo and return the URL plus an example insert/query. ``` ## Steps to follow - **Step 1: Provision Mongo.** ```bash curl -s -X POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"multi-repo-shared-scratchpad-mongo"}' | jq -r .connection_url ``` - **Step 2: Connect and pick a collection per branch.** ```python from pymongo import MongoClient m = MongoClient(os.environ["MONGO_URL"])["scratch"]["notes"] m.create_index([("branch", 1), ("ts", -1)]) ``` - **Step 3: Agent leaves a note.** ```python m.insert_one({ "branch": "feat/billing-rework", "agent": "frontend-1", "kind": "blocker", "ref": "packages/web/src/Checkout.tsx:142", "note": "Stripe element re-renders on form change; need useMemo", "ts": datetime.utcnow() }) ``` - **Step 4: Another agent reads the latest on that branch before starting.** ```python for n in m.find({"branch": "feat/billing-rework"}).sort("ts", -1).limit(20): print(n["agent"], n["note"]) ``` - **Step 5: GC stale branch notes weekly.** ```javascript db.notes.deleteMany({ ts: { $lt: new Date(Date.now() - 14*864e5) } }) ``` ## Why this works on instanode.dev Mongo's schemaless collections fit agent notes that drift in shape across repos, and the branch-keyed index makes cross-agent reads cheap. One curl produces a working URL — no Atlas account, no IP allowlist. ## Related cases - [Claude Code agent-teams scratchpad](/use-cases/claude-code-agent-teams-scratchpad) — Postgres-table version of the same coordination idea - [Coding-agent cross-session memory](/use-cases/coding-agent-cross-session-memory) — long-horizon memory across days, not just across repos - [Shared episodic memory store](/use-cases/shared-episodic-memory-store) — generalizes the scratchpad to non-coding agent pairs --- URL: /use-cases/obsidian-vault-embedding-sync.md --- --- title: Obsidian-vault embedding sync category: D. Personal AI services: ["pg"] scenario: A personal research agent embeds Obsidian notes nightly into pgvector and answers questions across years of writing. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a personal research agent embeds Obsidian notes nightly into pgvector and answers questions across years of writing. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Set up nightly Obsidian-vault embedding into pgvector on instanode. Provision Postgres, enable pgvector, walk `~/notes/`, chunk by heading, embed with text-embedding-3-small, upsert by path+hash. Expose a search() function I can call from my personal agent. ``` ## Steps to follow - **Step 1: Provision Postgres.** ```bash curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"obsidian-vault-embedding-sync-db"}' | jq -r .connection_url > .pg ``` - **Step 2: Enable pgvector and create the schema.** ```sql CREATE EXTENSION IF NOT EXISTS vector; CREATE TABLE chunks ( path text NOT NULL, heading text, hash text NOT NULL, body text, embedding vector(1536), PRIMARY KEY (path, hash) ); CREATE INDEX ON chunks USING hnsw (embedding vector_cosine_ops); ``` - **Step 3: Nightly sync script chunks by heading and upserts.** ```python for md in Path("~/notes").expanduser().rglob("*.md"): for h, body in chunk_by_heading(md.read_text()): h_hash = hashlib.sha256(body.encode()).hexdigest()[:16] emb = openai.embeddings.create(model="text-embedding-3-small", input=body).data[0].embedding pg.execute("""INSERT INTO chunks VALUES (%s,%s,%s,%s,%s) ON CONFLICT (path, hash) DO NOTHING""", str(md), h, h_hash, body, emb) ``` - **Step 4: cron entry.** ```bash 0 3 * * * cd ~/code/notes-embed && uv run sync.py >> sync.log 2>&1 ``` - **Step 5: search() the agent calls.** ```python def search(q, k=8): e = embed(q) return pg.fetch("SELECT path, heading, body FROM chunks ORDER BY embedding <=> %s LIMIT %s", e, k) ``` ## Why this works on instanode.dev pgvector ships in the Postgres you provision, so there is no separate vector store to operate. HNSW handles years of notes at low latency, and the same DB powers both your personal agent's RAG and any future search UI. ## Related cases - [Coding-agent cross-session memory](/use-cases/coding-agent-cross-session-memory) — same pgvector recall pattern over code instead of notes - [Daily-journal episodic memory](/use-cases/daily-journal-episodic-memory) — short-form personal counterpart to the long-form vault - [arXiv-and-RSS research feed](/use-cases/arxiv-and-rss-research-feed) — an upstream ingestion source that feeds into the vault --- URL: /use-cases/on-call-incident-response-agent.md --- --- title: On-call incident-response agent category: F. Developer tooling services: ["webhook", "pg"] scenario: An on-call agent listens for alert webhooks, executes a runbook, and posts the action log back into the incident ticket. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an on-call agent listens for alert webhooks, executes a runbook, and posts the action log back into the incident ticket. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build an on-call agent that receives PagerDuty webhooks, runs the matching runbook (kubectl describe, fetch error logs, restart deployment if safe), and posts the full action log back to the incident ticket. Provision a webhook receiver and Postgres to store action logs per incident. ``` ## Steps to follow - **Step 1: Provision the webhook and DB.** ```bash curl -s -X POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"on-call-incident-response-agent-webhook"}' | tee /tmp/wh.json curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"on-call-incident-response-agent-db"}' ``` - **Step 2: Tell PagerDuty the receiver URL** from the response. ```bash jq -r .receive_url /tmp/wh.json # paste into PagerDuty -> Integrations -> Webhooks V3 ``` - **Step 3: Action-log schema.** ```sql CREATE TABLE actions ( incident_id text, step int, command text, output text, exit_code int, at timestamptz DEFAULT now(), PRIMARY KEY (incident_id, step) ); ``` - **Step 4: Poller fetches buffered alerts and runs the runbook.** ```python for alert in fetch_buffered(WH_URL): runbook = pick_runbook(alert["service"], alert["summary"]) for i, cmd in enumerate(runbook): out = run_safely(cmd, allowlist=["kubectl", "stern"]) pg.execute("INSERT INTO actions VALUES (%s,%s,%s,%s,%s)", alert["incident_id"], i, cmd, out.text, out.code) ``` - **Step 5: Post the log back to the ticket.** ```python log = pg.fetch("SELECT step,command,output FROM actions WHERE incident_id=%s ORDER BY step", inc) pagerduty.notes.create(incident_id=inc, content=render_md(log)) ``` ## Why this works on instanode.dev The webhook receiver buffers alerts during a paging storm, so the agent processes the queue rather than hammering your runbook tooling in parallel. Action logs in Postgres give post-incident retros a clean audit trail without standing up a separate logging stack. ## Related cases - [Deploy-status MCP server](/use-cases/deploy-status-mcp-server) — live status the on-call agent reads while running a runbook - [Slack/Discord async bot factory](/use-cases/slack-discord-async-bot-factory) — another webhook-driven durable bot pattern - [CI flake-tracker](/use-cases/ci-flake-tracker) — consumes the alerts that flaky-test detection often generates --- URL: /use-cases/one-afternoon-mvp-backend.md --- --- title: One-afternoon MVP backend category: H. Indie & SaaS founders services: ["pg", "redis", "deploy"] scenario: A solo founder spins up Postgres + Redis from a curl call in their Claude Code session and ships a paid product by evening. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a solo founder spins up Postgres + Redis from a curl call in their Claude Code session and ships a paid product by evening. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + Redis + container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` It's Sunday 2pm. I want to ship a paid waitlist for an indie SaaS called Inboxbird (AI triage for shared inboxes) before bed tonight. From inside Claude Code: provision Postgres + Redis + a container deploy on instanode.dev, scaffold a Fastify + Drizzle backend with a /signup endpoint that takes an email and creates a Stripe checkout session for the $29/mo plan, store the pending session_id in Redis with a 1-hour TTL, write the email + Stripe customer ID to Postgres on webhook confirmation, deploy the container, and print the live URL so I can paste it on Twitter. Stripe keys are in ~/.stripe-keys; pull them through. ``` ## Steps to follow We'll thread one app — **Inboxbird**, a waitlist that takes $29/mo via Stripe — through every step. By the last command you'll have a live URL. - **Step 1: Provision the trio.** Three curls, three connection strings, one `.env` file. No console, no IAM, no project picker. ```bash mkdir inboxbird && cd inboxbird PG=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"one-afternoon-mvp-backend-db"}' | jq -r .connection_url) RD=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"one-afternoon-mvp-backend-cache"}' | jq -r .connection_url) cat > .env < { const { email } = z.object({ email: z.string().email() }).parse(req.body) const session = await stripe.checkout.sessions.create({ mode: 'subscription', customer_email: email, line_items: [{ price: process.env.STRIPE_PRICE_ID!, quantity: 1 }], success_url: 'https://inboxbird.instanode.app/welcome?s={CHECKOUT_SESSION_ID}', cancel_url: 'https://inboxbird.instanode.app/', }) await redis.setex(`pending:${session.id}`, 3600, email) return { url: session.url } }) ``` - **Step 4: Stripe webhook confirms the row.** When Stripe POSTs the `checkout.session.completed` event, we hydrate the signup from Redis and write it to Postgres. ```typescript app.post('/stripe/webhook', async (req, reply) => { const evt = stripe.webhooks.constructEvent(req.rawBody, req.headers['stripe-signature']!, process.env.STRIPE_WEBHOOK_SECRET!) if (evt.type === 'checkout.session.completed') { const s = evt.data.object as Stripe.Checkout.Session const email = await redis.get(`pending:${s.id}`) if (email) { await db.insert(signups).values({ email, stripe_cust: s.customer as string, plan: 'paid' }).onConflictDoUpdate({ target: signups.email, set: { plan: 'paid', stripe_cust: s.customer as string } }) await redis.del(`pending:${s.id}`) } } return { received: true } }) ``` - **Step 5: Ship it.** Dockerfile is the standard Node 20 image; `/deploy/new` does the rest and returns a real DNS URL. ```bash curl -sX POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $INSTANODE_TOKEN" \ -F "name=inboxbird" \ -F "dockerfile=Dockerfile" \ -F "subdomain=inboxbird" \ -F "env_vars=$(jq -Rs 'split("\n") | map(select(length>0) | split("=")) | map({(.[0]): (.[1:] | join("="))}) | add' < .env)" \ | jq -r .url # https://inboxbird.instanode.app ``` - **Step 6: Verify it's alive.** Hit the health check, then the signup path end-to-end. ```bash curl -s https://inboxbird.instanode.app/healthz # {"ok":true,"db":"up","redis":"up"} curl -s -X POST https://inboxbird.instanode.app/signup \ -H 'Content-Type: application/json' \ -d '{"email":"first-customer@example.com"}' # {"url":"https://checkout.stripe.com/c/pay/cs_live_..."} ``` ## Why this works on instanode.dev The "Sunday-night ship" used to mean four signups — **Vercel** for the front, **Supabase** for the DB, **Upstash** for Redis, **Fly.io** or **Render** for the container — four dashboards, four billing relationships, four IAM models the founder has to reason about at midnight. Each one is good in isolation, but the seams between them are where the afternoon goes: Supabase's connection string format vs. Drizzle's expectations, Upstash's TLS flag, Fly's secret CLI, Vercel's build cache. instanode collapses the four into one claimed token: the same JWT that owns the DB owns the cache and the deploy URL, and `instanode.app` is real DNS — not a `*.fly.dev` you have to CNAME later. By the time Stripe sends its first webhook, the founder has spent zero minutes in a cloud console and the whole month's infra bills as one $9 hobby-tier line item until they outgrow it. ## Related cases - [Full dev backend in one curl](/use-cases/full-dev-backend-in-one-curl) — the no-deploy precursor to this paid-by-evening ship flow - [Side-project container deploy](/use-cases/side-project-container-deploy) — bare deploy primitive this MVP flow calls into - [AI cofounder spawns a startup](/use-cases/ai-cofounder-spawns-a-startup) — agent-driven variant where the founder is an AI --- URL: /use-cases/openai-agents-sdk-handoff-mesh.md --- --- title: OpenAI Agents SDK handoff mesh category: J. Agent swarms & fan-out services: ["pg", "redis"] scenario: A triage agent hands off to specialist agents (refund, shipping, fraud) running concurrently, each maintaining its own conversation thread row keyed by handoff_id. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a triage agent hands off to specialist agents (refund, shipping, fraud) running concurrently, each maintaining its own conversation thread row keyed by handoff_id. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Use the OpenAI Agents SDK to wire a triage agent that hands off to refund, shipping, and fraud specialists. Each specialist runs concurrently and maintains its own thread keyed by handoff_id in Postgres. Use Redis for in-flight handoff locks to prevent duplicate work. Provision both and return URLs. ``` ## Steps to follow - **Step 1: Provision Postgres and Redis.** ```bash curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"openai-agents-sdk-handoff-mesh-db"}' curl -s -X POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"openai-agents-sdk-handoff-mesh-cache"}' ``` - **Step 2: Threads schema.** ```sql CREATE TABLE threads ( handoff_id uuid PRIMARY KEY, specialist text NOT NULL, messages jsonb NOT NULL DEFAULT '[]', status text DEFAULT 'open', updated_at timestamptz DEFAULT now() ); ``` - **Step 3: Lock + create thread on handoff.** ```python async def handoff(specialist, payload): hid = uuid4() if not await redis.set(f"lock:{hid}", "1", nx=True, ex=300): return None pg.execute("INSERT INTO threads(handoff_id, specialist) VALUES (%s,%s)", hid, specialist) return hid ``` - **Step 4: Wire the SDK with handoffs.** ```python from agents import Agent, handoff refund = Agent(name="refund", instructions="...") shipping = Agent(name="shipping", instructions="...") triage = Agent(name="triage", handoffs=[handoff(refund), handoff(shipping)]) ``` - **Step 5: Append messages to the thread row.** ```sql UPDATE threads SET messages = messages || $1::jsonb, updated_at = now() WHERE handoff_id = $2; ``` ## Why this works on instanode.dev Postgres' `jsonb || jsonb` makes per-thread message appending atomic, and Redis NX locks stop the same handoff from being claimed twice when the triage agent retries. Two curls, both in the same token, no per-environment config drift. ## Related cases - [CrewAI parallel-process crew](/use-cases/crewai-parallel-process-crew) — framework-equivalent specialist-agent fan-out - [Cross-framework A2A gateway](/use-cases/cross-framework-a2a-gateway) — translates OpenAI SDK handoffs into other frameworks - [LangGraph fan-out research agents](/use-cases/langgraph-fan-out-research-agents) — graph-shaped alternative to a flat handoff mesh --- URL: /use-cases/opentelemetry-agent-trace-ingest.md --- --- title: OpenTelemetry agent-trace ingest category: N. Multi-agent observability services: ["webhook", "pg", "storage"] scenario: A Langfuse-style collector receives OTel spans from 200 concurrent agents via a webhook endpoint, writes them to Postgres, and stores large prompt payloads in S3-compatible storage. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Langfuse-style collector receives OTel spans from 200 concurrent agents via a webhook endpoint, writes them to Postgres, and stores large prompt payloads in S3-compatible storage. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + Postgres + S3-compatible storage) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build a Langfuse-style OTel ingestor for our 200-agent swarm. Spans arrive on a webhook endpoint, get unpacked into Postgres for query, and large prompt/response bodies overflow to S3-compatible storage with a pointer back. Provision webhook, Postgres, and S3-compatible storage. ``` ## Steps to follow - **Step 1: Provision all three.** ```bash curl -s -X POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"opentelemetry-agent-trace-ingest-webhook"}' curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"opentelemetry-agent-trace-ingest-db"}' curl -s -X POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"opentelemetry-agent-trace-ingest-storage"}' ``` - **Step 2: Spans table.** ```sql CREATE TABLE spans ( trace_id text, span_id text PRIMARY KEY, parent_id text, name text, started_at timestamptz, duration_ms int, attributes jsonb, body_key text ); CREATE INDEX ON spans (trace_id); CREATE INDEX ON spans (started_at DESC); ``` - **Step 3: Point the OTel SDK at the receiver URL.** ```python from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter exporter = OTLPSpanExporter(endpoint=f"{WH_URL}/v1/traces") ``` - **Step 4: Ingest worker offloads large bodies to S3-compatible storage.** ```python for span in fetch_webhook_batch(): body = span["attributes"].pop("llm.prompt", None) key = None if body and len(body) > 8192: key = f"prompts/{span['trace_id']}/{span['span_id']}.txt" s3.put_object(Bucket="otel", Key=key, Body=body) pg.execute("INSERT INTO spans VALUES (...)", ..., key) ``` - **Step 5: Query a slow trace.** ```sql SELECT name, duration_ms, attributes FROM spans WHERE trace_id = $1 ORDER BY started_at; ``` ## Why this works on instanode.dev The webhook absorbs bursts when 200 agents flush at once; S3-compatible storage keeps Postgres rows skinny by holding the 50KB prompt bodies; the trace dashboard joins them on demand. One claimed token, three resources, zero observability vendor lock-in. ## Related cases - [Agent-run lineage store](/use-cases/agent-run-lineage-store) — uses these spans to build the parent/child run graph - [Cross-agent replay debugger](/use-cases/cross-agent-replay-debugger) — replays branches of the trace stream this collector ingests - [Token-cost ledger per sub-agent](/use-cases/token-cost-ledger-per-sub-agent) — spend-aggregation view over the same span firehose --- URL: /use-cases/overnight-dossier-fleet.md --- --- title: Overnight dossier fleet category: Q. Background/async agent fleets services: ["mongo", "storage"] scenario: An async research service queues hundreds of overnight dossier jobs; workers persist intermediate findings in Mongo and PDF outputs in S3-compatible storage when complete. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an async research service queues hundreds of overnight dossier jobs; workers persist intermediate findings in Mongo and PDF outputs in S3-compatible storage when complete. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (MongoDB + S3-compatible storage) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Spin up an overnight research fleet: queue 400 dossier jobs at 11pm, each worker persists intermediate findings to Mongo (flexible schema) and uploads the final PDF to S3-compatible storage. By 7am I want a manifest of completed dossiers with their PDF URLs. Provision Mongo and S3-compatible storage. ``` ## Steps to follow - **Step 1: Provision the stores.** ```bash curl -s -X POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"overnight-dossier-fleet-mongo"}' curl -s -X POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"overnight-dossier-fleet-storage"}' ``` - **Step 2: Seed the job collection.** ```python m["jobs"].insert_many([ {"_id": str(uuid4()), "subject": s, "status": "queued"} for s in subjects ]) m["jobs"].create_index([("status", 1)]) ``` - **Step 3: Worker pulls a job, streams partials.** ```python job = m["jobs"].find_one_and_update({"status": "queued"}, {"$set": {"status": "running"}}) for step in research(job["subject"]): m["partials"].insert_one({"job": job["_id"], "step": step.name, "data": step.data}) ``` - **Step 4: Upload the PDF on completion.** ```python pdf_key = f"dossiers/{job['_id']}.pdf" s3.put_object(Bucket="reports", Key=pdf_key, Body=render_pdf(job)) m["jobs"].update_one({"_id": job["_id"]}, {"$set": {"status": "done", "pdf": pdf_key}}) ``` - **Step 5: Morning manifest.** ```javascript db.jobs.find({status: "done"}, {subject: 1, pdf: 1}) ``` ## Why this works on instanode.dev Mongo's flexible docs hold the intermediate findings even when sub-agents return wildly different shapes, and S3-compatible storage holds the final PDFs cheaply. One token claims both; the morning manifest is a single `find()` away. ## Related cases - [Cron-scheduled scraping swarm](/use-cases/cron-scheduled-scraping-swarm) — scheduled producer of the same kind of background research jobs - [Inbox-zero agent fleet](/use-cases/inbox-zero-agent-fleet) — another async fleet writing Mongo + S3-compatible storage outputs per user - [arXiv-and-RSS research feed](/use-cases/arxiv-and-rss-research-feed) — an upstream input source for dossier topics --- URL: /use-cases/parallel-sql-plan-probe.md --- --- title: Parallel SQL-plan probe category: M. Parallel tool execution services: ["pg", "redis"] scenario: A data-analyst agent issues 12 candidate EXPLAIN ANALYZE queries against a forked Postgres in parallel, picking the lowest-cost plan to run against the real DB. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a data-analyst agent issues 12 candidate EXPLAIN ANALYZE queries against a forked Postgres in parallel, picking the lowest-cost plan to run against the real DB. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Probe 12 candidate query rewrites in parallel against a forked Postgres. Each probe runs EXPLAIN ANALYZE, the lowest-cost plan wins, and we cache the chosen rewrite per query-shape hash in Redis so we don't re-probe on the next call. Provision a fresh Postgres and Redis. ``` ## Steps to follow - **Step 1: Provision the fork-target DB and Redis.** ```bash PG=$(curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"parallel-sql-plan-probe-db"}' | jq -r .connection_url) RD=$(curl -s -X POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"parallel-sql-plan-probe-cache"}' | jq -r .connection_url) ``` - **Step 2: Seed it with a snapshot from production.** ```bash pg_dump $PROD_URL --schema-only | psql $PG pg_dump $PROD_URL --data-only --table=orders --table=users | psql $PG ``` - **Step 3: Run 12 EXPLAINs concurrently.** ```python async def explain(sql): async with pool.acquire() as c: return await c.fetchval(f"EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) {sql}") costs = await asyncio.gather(*[explain(s) for s in candidates]) best = min(zip(candidates, costs), key=lambda x: x[1][0]["Plan"]["Total Cost"]) ``` - **Step 4: Cache the winning rewrite.** ```python await redis.setex(f"plan:{shape_hash(original_sql)}", 3600, best[0]) ``` - **Step 5: Next call peeks the cache.** ```python cached = await redis.get(f"plan:{shape_hash(sql)}") return cached.decode() if cached else None ``` ## Why this works on instanode.dev Spinning up a throwaway Postgres for plan probing used to take an RDS dashboard tour; here it's one curl that returns a connection string in a second. Redis caches plan decisions so a hot query shape is probed once an hour, not once a request. ## Related cases - [Copy-on-write Postgres for agent migrations](/use-cases/copy-on-write-postgres-for-agent-migrations) — the forking primitive this probe runs EXPLAINs against - [Ephemeral test database for a risky migration](/use-cases/ephemeral-test-database-for-a-risky-migration) — single-clone alternative when you only need one probe - [Anthropic parallel tool_use batch](/use-cases/anthropic-parallel-tool-use-batch) — same fan-out-and-pick-best shape, applied to model tools --- URL: /use-cases/per-agent-dead-letter-inspection-queue.md --- --- title: Per-agent dead-letter inspection queue category: N. Multi-agent observability services: ["nats", "mongo"] scenario: Every failed tool call from a swarm is republished to a NATS DLQ; an investigator agent pulls them in batches, classifies the failure mode, and persists clusters in Mongo for the operator UI. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: every failed tool call from a swarm is republished to a NATS DLQ; an investigator agent pulls them in batches, classifies the failure mode, and persists clusters in Mongo for the operator UI. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream + MongoDB) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Every failed tool call across the swarm publishes to a NATS DLQ subject. Build an investigator agent that consumes the DLQ in batches of 50, classifies the failure (rate-limit, auth, timeout, schema-mismatch), and writes clusters to Mongo for the operator UI. Provision NATS and Mongo. ``` ## Steps to follow - **Step 1: Provision queue and store.** ```bash curl -s -X POST https://api.instanode.dev/queue/new -d '{"name":"per-agent-dead-letter-inspection-q-queue","stream":"dlq"}' -H 'Content-Type: application/json' curl -s -X POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"per-agent-dead-letter-inspection-q-mongo"}' ``` - **Step 2: Workers publish failures to the DLQ.** ```python except Exception as e: await js.publish("dlq.tool", json.dumps({ "agent": agent_id, "tool": tool, "args": args, "err": str(e), "stack": traceback.format_exc(), "at": time.time() }).encode()) ``` - **Step 3: Investigator pulls in batches.** ```python sub = await js.pull_subscribe("dlq.tool", durable="inspector") while True: batch = await sub.fetch(50, timeout=30) classify_and_cluster([json.loads(m.data) for m in batch]) for m in batch: await m.ack() ``` - **Step 4: Cluster docs in Mongo.** ```python m["clusters"].update_one( {"signature": sig}, {"$inc": {"count": 1}, "$push": {"examples": {"$each": [example], "$slice": -20}}, "$set": {"last_seen": datetime.utcnow()}}, upsert=True ) ``` - **Step 5: Operator UI query.** ```javascript db.clusters.find().sort({count: -1}).limit(20) ``` ## Why this works on instanode.dev JetStream's durable pull-consumers let the investigator fall behind during a failure storm without losing messages. Mongo's update-with-upsert collapses thousands of failures into a top-N cluster list with one query. ## Related cases - [Durable agent task queue](/use-cases/durable-agent-task-queue) — the main queue whose failures feed this DLQ - [Live agent status broadcast](/use-cases/live-agent-status-broadcast) — complementary live-success-side view of the same swarm - [Agent-resilience chaos lab](/use-cases/agent-resilience-chaos-lab) — produces the failures the DLQ inspector ends up clustering --- URL: /use-cases/per-agent-rate-limited-api-key-vault.md --- --- title: Per-agent rate-limited API key vault category: O. Cross-agent commerce & payments services: ["redis", "pg"] scenario: A vault service mints scoped, rate-limited API keys for child agents on demand; Redis tracks per-key usage and the spend rolls up to a Postgres billing event stream. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a vault service mints scoped, rate-limited API keys for child agents on demand; Redis tracks per-key usage and the spend rolls up to a Postgres billing event stream. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Redis + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build a vault that mints scoped, rate-limited API keys for child agents on demand. Redis tracks per-key usage with sliding windows, and every charge rolls up to a Postgres billing event stream. Provision both and expose mint() and charge() endpoints. ``` ## Steps to follow - **Step 1: Provision Redis and Postgres.** ```bash curl -s -X POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"per-agent-rate-limited-api-key-vau-cache"}' curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"per-agent-rate-limited-api-key-vau-db"}' ``` - **Step 2: Billing event schema.** ```sql CREATE TABLE billing_events ( id bigserial PRIMARY KEY, parent_agent text NOT NULL, child_key text NOT NULL, units numeric NOT NULL, reason text, at timestamptz DEFAULT now() ); CREATE INDEX ON billing_events (parent_agent, at DESC); ``` - **Step 3: Mint a scoped key.** ```python def mint(parent, scopes, rpm): key = "vk_" + secrets.token_urlsafe(24) redis.hset(f"key:{key}", mapping={"parent": parent, "scopes": ",".join(scopes), "rpm": rpm}) return key ``` - **Step 4: Sliding-window check on each use.** ```python def allow(key): now = time.time() pipe = redis.pipeline() pipe.zremrangebyscore(f"rl:{key}", 0, now - 60) pipe.zadd(f"rl:{key}", {str(uuid4()): now}) pipe.zcard(f"rl:{key}") pipe.expire(f"rl:{key}", 70) _, _, count, _ = pipe.execute() return count <= int(redis.hget(f"key:{key}", "rpm")) ``` - **Step 5: Charge on each call.** ```sql INSERT INTO billing_events (parent_agent, child_key, units, reason) VALUES ($1, $2, $3, $4); ``` ## Why this works on instanode.dev Redis' sorted-set sliding windows are the canonical agent-rate-limit primitive, and Postgres keeps the immutable charge trail your finance system reconciles against. Two curls, no separate gateway service. ## Related cases - [Tool-call rate-limit and budget cache](/use-cases/tool-call-rate-limit-and-budget-cache) — the in-agent budget cache this vault rolls up into - [Token-cost ledger per sub-agent](/use-cases/token-cost-ledger-per-sub-agent) — consumes the vault's billing events for tenant-spend rollups - [x402 micropayment per tool call](/use-cases/x402-micropayment-per-tool-call) — payment-rail alternative to rate-limited keys for paid tools --- URL: /use-cases/per-device-edge-agent-state-sync.md --- --- title: Per-device edge-agent state sync category: R. Edge agents & federated swarms services: ["webhook", "pg"] scenario: An IoT fleet of 10,000 edge agents each runs on a Workers-style runtime, syncing local SQLite deltas to a central Postgres via webhook batches every minute. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an IoT fleet of 10,000 edge agents each runs on a Workers-style runtime, syncing local SQLite deltas to a central Postgres via webhook batches every minute. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` We've got 10,000 Workers-runtime edge agents each with a local SQLite. Every minute they batch their deltas and POST to a webhook receiver. A central worker drains the receiver, applies upserts to Postgres, and tracks last-sync per device. Provision webhook and Postgres. ``` ## Steps to follow - **Step 1: Provision the receiver and central DB.** ```bash curl -s -X POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"per-device-edge-agent-state-sync-webhook"}' curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"per-device-edge-agent-state-sync-db"}' ``` - **Step 2: Central schema.** ```sql CREATE TABLE device_state ( device_id text NOT NULL, key text NOT NULL, value jsonb, version bigint, PRIMARY KEY (device_id, key) ); CREATE TABLE sync_cursor (device_id text PRIMARY KEY, last_at timestamptz); ``` - **Step 3: Edge agent batches once a minute.** ```javascript setInterval(async () => { const deltas = await sqlite.all("SELECT * FROM outbox WHERE synced = 0") if (!deltas.length) return await fetch(env.WH_URL, { method: "POST", body: JSON.stringify({ device: env.ID, deltas }) }) await sqlite.exec("UPDATE outbox SET synced = 1") }, 60_000) ``` - **Step 4: Central drain worker.** ```python for msg in pull_webhook_batch(WH_URL, n=500): with pg.transaction(): for d in msg["deltas"]: pg.execute("""INSERT INTO device_state(device_id,key,value,version) VALUES (%s,%s,%s,%s) ON CONFLICT (device_id,key) DO UPDATE SET value=EXCLUDED.value, version=EXCLUDED.version WHERE device_state.version < EXCLUDED.version""", msg["device"], d["k"], d["v"], d["ver"]) pg.execute("INSERT INTO sync_cursor VALUES (%s, now()) ON CONFLICT (device_id) DO UPDATE SET last_at=now()", msg["device"]) ``` - **Step 5: Detect stragglers.** ```sql SELECT device_id, last_at FROM sync_cursor WHERE last_at < now() - interval '5 minutes'; ``` ## Why this works on instanode.dev The webhook receiver flattens 10k devices into a single buffered ingestion point, so the drain worker controls Postgres concurrency. Version-aware upserts make the sync idempotent across retries. ## Related cases - [Geo-sharded chat-agent fleet](/use-cases/geo-sharded-chat-agent-fleet) — region-scoped variant of the same edge-to-central sync idea - [Federated-learning aggregator](/use-cases/federated-learning-aggregator) — edge-fleet sibling that syncs gradients instead of SQLite deltas - [OpenTelemetry agent-trace ingest](/use-cases/opentelemetry-agent-trace-ingest) — similar webhook-batch ingestion at agent-fleet scale --- URL: /use-cases/per-tenant-chatbot-factory-at-signup.md --- --- title: Per-tenant chatbot factory at signup category: L. Agent-factory / spawning patterns services: ["mongo", "redis", "deploy"] scenario: When a B2B SaaS user clicks 'Add AI assistant', the factory provisions a dedicated Mongo for that tenant's chat history, a Redis for session state, and deploys an isolated agent container. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: when a B2B SaaS user clicks 'Add AI assistant', the factory provisions a dedicated Mongo for that tenant's chat history, a Redis for session state, and deploys an isolated agent container. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (MongoDB + Redis + container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` When a B2B tenant clicks "Add AI assistant," call /nosql/new for their chat history, /cache/new for session state, and /deploy/new for an isolated agent container with those URLs in env. Return the assistant URL to embed. Provision-on-signup, fully tenant-isolated. ``` ## Steps to follow - **Step 1: Tenant clicks the button — your factory backend runs:** ```bash MONGO=$(curl -s -X POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"per-tenant-chatbot-factory-at-sign-mongo"}' | jq -r .connection_url) REDIS=$(curl -s -X POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"per-tenant-chatbot-factory-at-sign-cache"}' | jq -r .connection_url) ``` - **Step 2: Deploy the agent container with tenant-scoped env.** ```bash curl -s -X POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $INSTANODE_TOKEN" \ -F "name=assistant-$TENANT" \ -F "image=ghcr.io/acme/assistant:latest" \ -F "env.MONGO_URL=$MONGO" \ -F "env.REDIS_URL=$REDIS" \ -F "env.TENANT_ID=$TENANT" \ | jq -r .url > assistant_url.txt ``` - **Step 3: Persist the mapping in the SaaS DB.** ```sql INSERT INTO tenant_assistants (tenant_id, mongo_url, redis_url, deploy_url) VALUES ($1, $2, $3, $4); ``` - **Step 4: Embed snippet returned to the tenant's app.** ```html ``` - **Step 5: Chat handler in the deployed agent.** ```python await mongo.history.insert_one({"tenant": TENANT_ID, "role": "user", "text": msg}) state = await redis.get(f"session:{user_id}") ``` ## Why this works on instanode.dev Three resources per tenant, claimed under your factory's token, deploy in seconds — no Kubernetes namespace creation, no per-tenant Helm chart. Each assistant is isolated at the URL and DB level, which is the only isolation B2B buyers actually verify. ## Related cases - [AgentCore tenant-scoped spawning](/use-cases/agentcore-tenant-scoped-spawning) — lighter-weight tenant runtime without the chatbot UI - [Cloudflare sub-agent factory per user](/use-cases/cloudflare-sub-agent-factory-per-user) — per-user variant of the same factory pattern - [Inbox-zero agent fleet](/use-cases/inbox-zero-agent-fleet) — per-user durable-agent shape adjacent to per-tenant --- URL: /use-cases/personal-injury-demand-letters.md --- --- title: Personal-injury demand letters category: C. Vertical AI apps services: ["pg", "webhook"] scenario: A legal agent drafts demand letters from case files, stores prior versions, and emits webhooks to the firm's case-management system. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a legal agent drafts demand letters from case files, stores prior versions, and emits webhooks to the firm's case-management system. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + webhook receiver) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build a legal agent that drafts personal-injury demand letters from intake files. Each draft version persists to Postgres with full history, and on send we emit a webhook to Clio (the firm's case-management system) with the matter_id and PDF URL. Provision Postgres and a webhook sender endpoint. ``` ## Steps to follow - **Step 1: Provision Postgres and a webhook (we'll use it to forward to Clio).** ```bash curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"personal-injury-demand-letters-db"}' curl -s -X POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"personal-injury-demand-letters-webhook"}' ``` - **Step 2: Letter version schema.** ```sql CREATE TABLE letters ( matter_id text NOT NULL, version int NOT NULL, draft text NOT NULL, author text, created_at timestamptz DEFAULT now(), PRIMARY KEY (matter_id, version) ); CREATE INDEX ON letters (matter_id, version DESC); ``` - **Step 3: Drafting flow inside the agent.** ```python prior = pg.fetchrow("SELECT draft FROM letters WHERE matter_id=%s ORDER BY version DESC LIMIT 1", mid) intake = load_intake(mid) new_draft = llm.draft(intake=intake, prior=prior["draft"] if prior else None) pg.execute("INSERT INTO letters VALUES (%s,(SELECT coalesce(max(version),0)+1 FROM letters WHERE matter_id=%s),%s,%s)", mid, mid, new_draft, "agent-v3") ``` - **Step 4: On final send, POST to Clio via webhook.** ```python requests.post(CLIO_WEBHOOK, json={ "matter_id": mid, "pdf_url": uploaded_pdf, "sent_at": datetime.utcnow().isoformat() }) ``` - **Step 5: Audit query — every version of a matter.** ```sql SELECT version, author, created_at FROM letters WHERE matter_id=$1 ORDER BY version; ``` ## Why this works on instanode.dev Letters need a complete edit history for malpractice defense; Postgres versioning gives it cheaply. The webhook receiver lets you decouple from Clio's API quirks — buffer first, retry second. ## Related cases - [Clinical-scribe note storage](/use-cases/clinical-scribe-note-storage) — another vertical-AI workflow with versioned per-case docs - [Contract redline cache](/use-cases/contract-redline-cache) — adjacent legal-AI workflow that caches clause embeddings - [AML transaction monitor](/use-cases/aml-transaction-monitor) — compliance-flavored sibling with full auditable reasoning trace --- URL: /use-cases/pr-review-bot-triggered-by-webhooks.md --- --- title: PR-review bot triggered by webhooks category: A. AI coding agents services: ["webhook", "redis"] scenario: A code-review agent receives PR webhooks from GitHub, posts inline comments, and re-reviews on each push while caching diffs between runs. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a code-review agent receives PR webhooks from GitHub, posts inline comments, and re-reviews on each push while caching diffs between runs. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Wire a GitHub PR-review agent. Provision a webhook to receive pull_request and push events, cache the diff per PR head SHA in Redis (so re-reviews on the same SHA are free), and post inline comments via the GitHub API. Return the receiver URL to paste into GitHub's webhook settings. ``` ## Steps to follow - **Step 1: Provision the receiver and the cache.** ```bash curl -s -X POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"pr-review-bot-triggered-by-webhook-webhook"}' | tee /tmp/wh.json curl -s -X POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"pr-review-bot-triggered-by-webhook-cache"}' ``` - **Step 2: Configure the GitHub webhook.** ```bash URL=$(jq -r .receive_url /tmp/wh.json) gh api repos/acme/api/hooks -f name=web -f config[url]="$URL" \ -f config[content_type]=json -F events[]=pull_request -F events[]=push ``` - **Step 3: Poller picks up events and caches diffs.** ```python for ev in fetch_events(WH_URL): pr = ev["pull_request"] key = f"diff:{pr['head']['sha']}" diff = await redis.get(key) if not diff: diff = gh.pr_diff(pr["number"]).encode() await redis.setex(key, 86400, diff) review(pr, diff.decode()) ``` - **Step 4: Post inline comments.** ```python for c in comments: gh.create_review_comment(pr_number=pr["number"], body=c.body, commit_id=pr["head"]["sha"], path=c.path, line=c.line) ``` - **Step 5: Re-reviews on same SHA hit the cache.** ```bash redis-cli get "diff:abc123" # already there, no GitHub round-trip ``` ## Why this works on instanode.dev The webhook receiver shields you from GitHub's retry storms when a deploy fails — events queue up rather than getting dropped. The Redis diff cache keeps repeat reviews on the same SHA cheap, which matters when a busy PR gets 5 force-pushes in an hour. ## Related cases - [High-volume PR-review pipeline](/use-cases/high-volume-pr-review-pipeline) — the at-scale queue-and-S3-compatible storage version of the same bot - [Devin-style PR-bot fleet](/use-cases/devin-style-pr-bot-fleet) — per-issue ephemeral-worker variant with a scratch Postgres - [CI flake-tracker](/use-cases/ci-flake-tracker) — consumes the same GitHub webhook stream from a different angle --- URL: /use-cases/pre-commit-skill-scanner-webhook.md --- --- title: Pre-commit skill-scanner webhook category: F. Developer tooling services: ["webhook"] scenario: An MCP skill security scanner receives pre-commit webhooks, scans agent skills against a ruleset, and blocks the push on critical findings. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an MCP skill security scanner receives pre-commit webhooks, scans agent skills against a ruleset, and blocks the push on critical findings. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Set up a pre-commit MCP-skill security scanner. Provision a webhook endpoint; configure husky/pre-commit hooks in our repos to POST the staged skill files. The scanner runs a rule set (shell out, network egress, unbounded eval) and replies non-200 to block on critical findings. Return the URL. ``` ## Steps to follow - **Step 1: Provision the webhook.** ```bash curl -s -X POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"pre-commit-skill-scanner-webhook-webhook"}' | jq -r .receive_url ``` - **Step 2: Wire the pre-commit hook.** ```bash cat > .git/hooks/pre-commit <<'SH' #!/usr/bin/env bash staged=$(git diff --cached --name-only --diff-filter=AM | grep -E '\.claude/skills/.*\.md$') [ -z "$staged" ] && exit 0 payload=$(jq -n --arg files "$(tar -czf - $staged | base64)" '{archive: $files}') code=$(curl -s -o /tmp/scan.json -w "%{http_code}" -XPOST "$WH_URL" -d "$payload") [ "$code" = "200" ] || { jq . /tmp/scan.json; exit 1; } SH chmod +x .git/hooks/pre-commit ``` - **Step 3: Scanner pulls submissions and applies the rule set.** ```python for sub in fetch_webhook_batch(WH_URL): findings = [] for path, body in untar(sub["archive"]): findings += run_rules(body, rules=["shell_out", "egress", "eval"]) verdict = "block" if any(f.severity == "critical" for f in findings) else "ok" ``` - **Step 4: Reply with verdict on the request the hook polls.** ```python # Hook polls /requests/{id} until verdict appears, then exit 0/1 accordingly. ``` - **Step 5: CI fallback** runs the same scan on PR-open so local-hook bypass still gets caught. ```yaml - run: ./.github/scripts/run-skill-scan.sh ``` ## Why this works on instanode.dev The webhook receiver gives the scanner a single ingress URL that every dev's hook can POST to, with no per-developer auth setup. Rules run server-side so your scanner improvements ship instantly without each developer running `pip install --upgrade`. ## Related cases - [Adversarial red-team runner](/use-cases/adversarial-red-team-runner) — runtime attack-surface counterpart to this static scanner - [PR-review bot triggered by webhooks](/use-cases/pr-review-bot-triggered-by-webhooks) — another webhook-triggered code-quality bot - [SARIF scan-result store](/use-cases/sarif-scan-result-store) — Postgres warehouse where scanner findings can land for trends --- URL: /use-cases/pre-launch-waitlist-store.md --- --- title: Pre-launch waitlist store category: H. Indie & SaaS founders services: ["webhook", "pg"] scenario: A landing page captures emails via a webhook receiver and stores them with UTM context for nurture campaigns. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a landing page captures emails via a webhook receiver and stores them with UTM context for nurture campaigns. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` For our pre-launch landing page, set up a waitlist capture. Provision a webhook the landing form POSTs to, and a Postgres table that the webhook drainer fills with email + UTM source/medium/campaign + timestamp. Output the receiver URL so I can wire the form. ``` ## Steps to follow - **Step 1: Provision the receiver and DB.** ```bash WH=$(curl -s -X POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"pre-launch-waitlist-store-webhook"}' | jq -r .receive_url) curl -s -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"pre-launch-waitlist-store-db"}' echo "Form action: $WH" ``` - **Step 2: Waitlist schema.** ```sql CREATE EXTENSION IF NOT EXISTS citext; CREATE TABLE waitlist ( id bigserial PRIMARY KEY, email citext UNIQUE NOT NULL, utm_source text, utm_medium text, utm_campaign text, referrer text, ip inet, created_at timestamptz DEFAULT now() ); ``` - **Step 3: Landing page form.** ```html
``` - **Step 4: Drainer inserts into Postgres.** ```python for r in fetch_webhook_batch(WH): pg.execute("""INSERT INTO waitlist(email, utm_source, utm_medium, utm_campaign, referrer, ip) VALUES (%s,%s,%s,%s,%s,%s) ON CONFLICT (email) DO NOTHING""", r["email"], r.get("utm_source"), r.get("utm_medium"), r.get("utm_campaign"), r.get("referrer"), r["_ip"]) ``` - **Step 5: Top channels report.** ```sql SELECT utm_source, count(*) FROM waitlist GROUP BY 1 ORDER BY 2 DESC LIMIT 10; ``` ## Why this works on instanode.dev Two curls replace a Mailchimp signup + a Zap + a Google Sheet, and your data lives in real Postgres so the nurture campaign queries are SQL instead of CSV exports. The webhook tolerates traffic spikes from HN frontpage without a single 503. ## Related cases - [Stripe-event entitlements](/use-cases/stripe-event-entitlements) — the post-launch payments side of the same indie-founder funnel - [AI cofounder spawns a startup](/use-cases/ai-cofounder-spawns-a-startup) — agent-driven generator of the landing page this waitlist sits on - [Solo-founder analytics warehouse](/use-cases/solo-founder-analytics-warehouse) — downstream Postgres where waitlist UTMs end up for analysis --- URL: /use-cases/pyodide-notebook-cell-agent-farm.md --- --- title: Pyodide notebook cell agent farm category: M. Parallel tool execution services: ["storage", "nats"] scenario: An analyst agent splits a 200-cell notebook across 30 Pyodide workers, each writing intermediate dataframes to S3-compatible storage so the planner can pull only the ones it needs. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an analyst agent splits a 200-cell notebook across 30 Pyodide workers, each writing intermediate dataframes to S3-compatible storage so the planner can pull only the ones it needs. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (S3-compatible storage + NATS JetStream) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Split notebook.ipynb across 30 Pyodide workers. Each worker should pull its cell range from a NATS subject "cells.work", execute it in-browser, and write the resulting Arrow dataframe to a shared S3-compatible bucket keyed by cell_id. Provision the S3-compatible bucket and NATS via instanode.dev, then emit "cells.done" with the object key when each cell completes. ``` ## Steps to follow - **Step 1: Provision the bucket.** One curl for shared intermediate storage. ```bash curl -X POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"pyodide-notebook-cell-agent-farm-storage"}' | tee storage.json export S3_URL=$(jq -r .connection_url storage.json) ``` - **Step 2: Provision NATS for work distribution.** JetStream gives durable, replayable cell assignments. ```bash curl -X POST https://api.instanode.dev/queue/new -H 'Content-Type: application/json' -d '{"name":"pyodide-notebook-cell-agent-farm-queue"}' | tee nats.json export NATS_URL=$(jq -r .connection_url nats.json) ``` - **Step 3: Planner publishes 200 cell jobs.** ```python import nats, json nc = await nats.connect(NATS_URL) js = nc.jetstream() for i, cell in enumerate(notebook.cells): await js.publish("cells.work", json.dumps({"id": i, "src": cell.source}).encode()) ``` - **Step 4: Each Pyodide worker pulls, executes, uploads.** ```python df.to_parquet(f"s3://{BUCKET}/cells/{cell_id}.parquet") await js.publish("cells.done", json.dumps({"id": cell_id, "key": f"cells/{cell_id}.parquet"}).encode()) ``` - **Step 5: Planner pulls only the dataframes it actually needs** by listing `cells.done` and fetching the referenced keys. ## Why this works on instanode.dev NATS JetStream is queue + durable log in one — workers can rejoin mid-run and replay missed cell assignments. S3-compatible storage is S3-API so the same `boto3` / `fsspec` code works in browser Pyodide and Node, and the bucket is provisioned in under a second with zero account setup. ## Related cases - [Daytona warm-pool data workspace](/use-cases/daytona-warm-pool-data-workspace) — another warm-pool of Python sandboxes for analyst agents - [Browser-agent action pool](/use-cases/browser-agent-action-pool) — same fan-out shape with browser tabs instead of notebook cells - [LangGraph fan-out research agents](/use-cases/langgraph-fan-out-research-agents) — fan-out planner+reducer pattern at the research level --- URL: /use-cases/replit-agent-preview-backend.md --- --- title: Replit-Agent preview backend category: K. Ephemeral agent runtimes services: ["pg", "deploy"] scenario: A Replit-Agent-style preview deploys a one-shot app with a 24h-TTL Postgres so a reviewer can poke at the prototype, then everything is collected when the share link expires. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Replit-Agent-style preview deploys a one-shot app with a 24h-TTL Postgres so a reviewer can poke at the prototype, then everything is collected when the share link expires. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build a 24-hour preview backend for this prototype. Provision an anonymous Postgres via instanode.dev (auto-expires in 24h), apply migrations from db/schema.sql, then deploy the FastAPI app from this repo to a public subdomain with DATABASE_URL injected. Print the share URL when done. ``` ## Steps to follow - **Step 1: Provision a 24h-TTL Postgres.** Anonymous tier expires automatically — no cleanup script needed. ```bash curl -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"replit-agent-preview-backend-db"}' | tee db.json export DATABASE_URL=$(jq -r .connection_url db.json) export DB_TOKEN=$(jq -r .token db.json) ``` - **Step 2: Apply schema.** ```bash psql "$DATABASE_URL" < db/schema.sql ``` - **Step 3: Deploy the FastAPI container.** `/deploy/new` accepts a Dockerfile build context and injects env vars. ```bash curl -X POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $INSTANODE_TOKEN" \ -F "name=prototype-pr-42" \ -F "image=ghcr.io/me/prototype:pr-42" \ -F "env.DATABASE_URL=$DATABASE_URL" | tee deploy.json export APP_URL=$(jq -r .url deploy.json) ``` - **Step 4: Hand the reviewer one URL.** ```bash echo "Share: $APP_URL (expires in 24h)" ``` - **Step 5: Cleanup is automatic.** The DB's 24h TTL on the anonymous tier reaps the resource; the deploy expires alongside it. ## Why this works on instanode.dev Anonymous-tier provisions have a 24-hour TTL baked in — exactly the lifecycle a preview backend needs. The token returned from `/db/new` is the same identity used by `/deploy/new`, so the same reviewer link covers both resources and they vanish together without orphaned infrastructure. ## Related cases - [Sandbox-per-PR preview deployment](/use-cases/sandbox-per-pr-preview-deployment) — PR-scoped variant of the same disposable-preview pattern - [E2B microVM sandbox per agent turn](/use-cases/e2b-microvm-sandbox-per-agent-turn) — per-turn alternative when previews don't need a share link - [Side-project container deploy](/use-cases/side-project-container-deploy) — the bare deploy primitive this preview backend wraps --- URL: /use-cases/repo-wide-code-dependency-graph.md --- --- title: Repo-wide code dependency graph category: A. AI coding agents services: ["pg"] scenario: An agent indexes a polyrepo into a blast-radius graph so it can answer "what breaks if I rename this function" before editing. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an agent indexes a polyrepo into a blast-radius graph so it can answer "what breaks if I rename this function" before editing. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Index every Go, Python, and TypeScript file in this monorepo into a blast-radius graph. Provision a Postgres via instanode.dev, create symbols/edges tables, walk the repo with tree-sitter, and insert one row per function definition plus one row per call edge. Then answer "what breaks if I rename pkg/auth.VerifyJWT". ``` ## Steps to follow - **Step 1: Provision Postgres.** ```bash curl -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"repo-wide-code-dependency-graph-db"}' | tee db.json export DATABASE_URL=$(jq -r .connection_url db.json) ``` - **Step 2: Create the graph schema.** ```sql CREATE TABLE symbols ( id BIGSERIAL PRIMARY KEY, repo TEXT, path TEXT, name TEXT, kind TEXT, line INT, UNIQUE(repo, path, name, line) ); CREATE TABLE edges ( src BIGINT REFERENCES symbols(id), dst BIGINT REFERENCES symbols(id), kind TEXT ); CREATE INDEX ON edges (dst); ``` - **Step 3: Walk the repo with tree-sitter and bulk-insert.** ```python for fn in walk_definitions(repo): sid = insert_symbol(fn) for callee in fn.calls: insert_edge(sid, resolve(callee), "calls") ``` - **Step 4: Blast-radius query.** ```sql WITH RECURSIVE callers AS ( SELECT src FROM edges WHERE dst = (SELECT id FROM symbols WHERE name='VerifyJWT') UNION SELECT e.src FROM edges e JOIN callers c ON e.dst = c.src ) SELECT path, name FROM symbols WHERE id IN (SELECT src FROM callers); ``` - **Step 5: Feed the result back into the agent's edit-planning step** before it touches the rename. ## Why this works on instanode.dev Postgres recursive CTEs make blast-radius traversal a single query, and provisioning takes one HTTP call so an agent can rebuild the index on every branch without managing a long-lived service. The 5GB pro tier holds millions of edges for a large monorepo. ## Related cases - [Coding-agent cross-session memory](/use-cases/coding-agent-cross-session-memory) — complementary architectural-memory store for the same coding agent - [Multi-repo shared scratchpad](/use-cases/multi-repo-shared-scratchpad) — cross-repo coordination view layered on top of the graph - [SARIF scan-result store](/use-cases/sarif-scan-result-store) — uses similar Postgres patterns for cross-commit graph drift --- URL: /use-cases/restate-style-durable-sidecar.md --- --- title: Restate-style durable sidecar category: Q. Background/async agent fleets services: ["pg"] scenario: A Restate sidecar intercepts agent HTTP tool calls and journals them to Postgres so any crash mid-run resumes deterministically without re-charging external APIs. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Restate sidecar intercepts agent HTTP tool calls and journals them to Postgres so any crash mid-run resumes deterministically without re-charging external APIs. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Stand up a Restate-style durable sidecar in front of this agent. Every outbound tool call (HTTP POST) is journaled to Postgres before it fires; on resume after a crash, replay the journal so already-completed calls return cached responses instead of re-charging the upstream API. Provision Postgres via instanode.dev and write the sidecar in Go. ``` ## Steps to follow - **Step 1: Provision Postgres.** ```bash curl -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"restate-style-durable-sidecar-db"}' | tee db.json export DATABASE_URL=$(jq -r .connection_url db.json) ``` - **Step 2: Create the journal.** ```sql CREATE TABLE journal ( run_id UUID, step_id INT, request_hash TEXT, response_body JSONB, completed_at TIMESTAMPTZ, PRIMARY KEY (run_id, step_id) ); ``` - **Step 3: Wrap every tool call in journal-first, fire-second.** ```go func DurableCall(runID string, stepID int, req *http.Request) ([]byte, error) { if row, ok := lookup(runID, stepID); ok { return row.Body, nil } resp, err := http.DefaultClient.Do(req) body, _ := io.ReadAll(resp.Body) mustExec("INSERT INTO journal VALUES ($1,$2,$3,$4,now()) ON CONFLICT DO NOTHING", runID, stepID, hash(req), body) return body, err } ``` - **Step 4: On agent restart, replay.** Load all rows for `run_id` and short-circuit each step. - **Step 5: Idempotency key on the upstream call** prevents the rare double-charge if a crash lands between HTTP request and `INSERT`. ## Why this works on instanode.dev Postgres provisioning in one curl makes the durable-sidecar pattern trivially deployable per-agent, not per-fleet. `ON CONFLICT DO NOTHING` plus the composite `(run_id, step_id)` key gives at-most-once semantics for every tool call — exactly the Restate guarantee — without running a separate workflow engine. ## Related cases - [LangGraph state checkpoints](/use-cases/langgraph-state-checkpoints) — in-graph alternative to this out-of-process sidecar - [Long-horizon Temporal agent workflow](/use-cases/long-horizon-temporal-agent-workflow) — Temporal-engine alternative when workflows last weeks - [Form-fill state machine](/use-cases/form-fill-state-machine) — concrete browser-agent instance of the same crash-resume idea --- URL: /use-cases/sandbox-per-pr-preview-deployment.md --- --- title: Sandbox-per-PR preview deployment category: K. Ephemeral agent runtimes services: ["pg", "storage", "deploy"] scenario: A reviewer agent provisions a throwaway storage bucket plus Postgres tied to a PR number, seeds it from a snapshot, and the whole thing is torn down when the PR closes. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a reviewer agent provisions a throwaway storage bucket plus Postgres tied to a PR number, seeds it from a snapshot, and the whole thing is torn down when the PR closes. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + S3-compatible storage + container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` On every PR opened against this repo, provision an isolated Postgres + S3-compatible bucket via instanode.dev, restore from the staging snapshot (s3://staging/snapshot.dump), and deploy the app container to pr-NNN.instanode.dev. On PR close, hit the delete endpoint for each resource. Pass the share URL back as a PR comment. ``` ## Steps to follow - **Step 1: Provision Postgres and S3-compatible storage for PR #42.** ```bash PR=42 DB=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"sandbox-per-pr-preview-deployment-db"}') BUCKET=$(curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"sandbox-per-pr-preview-deployment-storage"}') echo "$DB" > .preview/pr-$PR-db.json echo "$BUCKET" > .preview/pr-$PR-bucket.json ``` - **Step 2: Seed Postgres from snapshot.** ```bash pg_restore --clean --if-exists \ -d "$(jq -r .connection_url .preview/pr-$PR-db.json)" \ snapshots/staging.dump ``` - **Step 3: Mirror seed assets into the new bucket.** ```bash aws s3 sync s3://staging/fixtures/ \ s3://$(jq -r .bucket .preview/pr-$PR-bucket.json)/ \ --endpoint-url https://s3.instanode.dev ``` - **Step 4: Deploy the app.** ```bash curl -X POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $INSTANODE_TOKEN" \ -F "name=pr-$PR-preview" \ -F "image=ghcr.io/me/app:pr-$PR" \ -F "subdomain=pr-$PR" ``` - **Step 5: On PR close, fan-out deletes** — `DELETE /api/v1/resources/:id` per resource (using each resource's `id` from its provision response, with a Bearer session token). Anonymous-tier resources also auto-reap at the 24h TTL, so a missed delete is bounded. ## Why this works on instanode.dev One token per resource means GitHub Actions can pass three opaque strings instead of three sets of credentials. `/storage/new` and `/db/new` complete in a single second each, so the preview is ready before CI finishes its first test. ## Related cases - [Cursor background-agent worktree](/use-cases/cursor-background-agent-worktree) — IDE-side counterpart that owns the worktree for the same PR - [Replit-Agent preview backend](/use-cases/replit-agent-preview-backend) — share-link variant of the same disposable-preview pattern - [Devin-style PR-bot fleet](/use-cases/devin-style-pr-bot-fleet) — agent worker that lands changes inside this preview env --- URL: /use-cases/sandboxed-test-runner-per-task.md --- --- title: Sandboxed test runner per task category: A. AI coding agents services: ["deploy"] scenario: A coding agent spins up a throwaway container per task to run the user's test suite in isolation, tears it down on success or failure. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a coding agent spins up a throwaway container per task to run the user's test suite in isolation, tears it down on success or failure. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` For each task in tasks.jsonl, deploy a throwaway container via instanode.dev /deploy/new running the user's test suite. Mount their repo as a volume, run `pytest -x`, capture exit code and last 200 lines of stdout, then call /deploy/delete. Aggregate pass/fail to results.csv. ``` ## Steps to follow - **Step 1: Build the runner image once.** ```dockerfile FROM python:3.12-slim RUN pip install pytest pytest-json-report ENTRYPOINT ["pytest", "-x", "--json-report", "--json-report-file=/out/report.json"] ``` - **Step 2: Spawn one container per task.** `/deploy/new` is multipart — pass `name`, `image`, and any `env.*` as form fields. ```bash for task in $(cat tasks.jsonl); do REPO=$(echo "$task" | jq -r .repo) DEPLOY=$(curl -sX POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $INSTANODE_TOKEN" \ -F "name=test-runner-$(echo "$REPO" | tr '/' '-')" \ -F "image=ghcr.io/me/runner:latest" \ -F "env.REPO=$REPO") echo "$DEPLOY" >> deploys.jsonl done ``` - **Step 3: Poll for completion.** ```bash while read d; do ID=$(echo "$d" | jq -r .id) curl -s "https://api.instanode.dev/deploy/$ID/logs" \ -H "Authorization: Bearer $INSTANODE_TOKEN" | tail -200 done < deploys.jsonl ``` - **Step 4: Tear down each on exit.** ```bash curl -sX DELETE "https://api.instanode.dev/deploy/$ID" \ -H "Authorization: Bearer $INSTANODE_TOKEN" ``` - **Step 5: Aggregate** exit codes into results.csv for the planner agent to consume. ## Why this works on instanode.dev `/deploy/new` returns in under a second and the deploy is fully isolated per token — no shared kernel state between tasks. Anonymous-tier deploys auto-expire in 24h, so a forgotten teardown won't leak a runner forever. ## Related cases - [E2B microVM sandbox per agent turn](/use-cases/e2b-microvm-sandbox-per-agent-turn) — per-turn variant of the same throwaway-container idea - [Daytona warm-pool data workspace](/use-cases/daytona-warm-pool-data-workspace) — warm-pool alternative when cold-start cost matters - [Terminal-Bench shell sandbox grid](/use-cases/terminal-bench-shell-sandbox-grid) — fleet-scale version with 100 parallel sandboxes --- URL: /use-cases/sarif-scan-result-store.md --- --- title: SARIF scan-result store category: F. Developer tooling services: ["pg"] scenario: A security scanner posts SARIF results into Postgres so trend dashboards show drift over weeks of commits. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a security scanner posts SARIF results into Postgres so trend dashboards show drift over weeks of commits. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Every nightly run of Semgrep and CodeQL on the main branch should POST its SARIF output to a Postgres table provisioned via instanode.dev. Build a small ingester that flattens SARIF results into rows keyed by (rule_id, commit_sha, file, line), so the dashboard can plot drift over weeks. ``` ## Steps to follow - **Step 1: Provision Postgres.** ```bash curl -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"sarif-scan-result-store-db"}' | tee db.json export DATABASE_URL=$(jq -r .connection_url db.json) ``` - **Step 2: Create the flat findings table.** ```sql CREATE TABLE findings ( id BIGSERIAL PRIMARY KEY, scanner TEXT, commit_sha TEXT, rule_id TEXT, severity TEXT, file TEXT, line INT, message TEXT, scanned_at TIMESTAMPTZ DEFAULT now() ); CREATE INDEX ON findings (commit_sha); CREATE INDEX ON findings (rule_id, scanned_at); ``` - **Step 3: Flatten and bulk-insert SARIF.** ```python import json, psycopg sarif = json.load(open("semgrep.sarif")) rows = [(r["ruleId"], commit, loc["physicalLocation"]["artifactLocation"]["uri"], loc["physicalLocation"]["region"]["startLine"], r["message"]["text"]) for run in sarif["runs"] for r in run["results"] for loc in r["locations"]] with psycopg.connect(DATABASE_URL) as c: c.cursor().executemany( "INSERT INTO findings(rule_id,commit_sha,file,line,message) VALUES (%s,%s,%s,%s,%s)", rows) ``` - **Step 4: Trend query.** ```sql SELECT date_trunc('day', scanned_at) d, rule_id, count(*) FROM findings GROUP BY 1,2 ORDER BY 1 DESC; ``` - **Step 5: Wire the dashboard** to that query and the agent can answer "are we getting better or worse on XSS findings". ## Why this works on instanode.dev A real Postgres on one curl removes the awkward step where security tools store results in a CI artifact and you can never query history. JSONB columns also handle the raw SARIF payload for downstream tooling that needs the original. ## Related cases - [CI flake-tracker](/use-cases/ci-flake-tracker) — another CI-side Postgres warehouse for tracking drift - [Pre-commit skill-scanner webhook](/use-cases/pre-commit-skill-scanner-webhook) — the inbound scanner that fills a SARIF store - [Repo-wide code dependency graph](/use-cases/repo-wide-code-dependency-graph) — blast-radius context for findings stored in SARIF --- URL: /use-cases/scatter-gather-price-comparison-swarm.md --- --- title: Scatter-gather price comparison swarm category: J. Agent swarms & fan-out services: ["nats", "redis"] scenario: A consumer agent broadcasts a product query to 40 retailer-specific shopper agents over a NATS subject; the first 5 cheapest replies win and the rest are cancelled mid-flight. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a consumer agent broadcasts a product query to 40 retailer-specific shopper agents over a NATS subject; the first 5 cheapest replies win and the rest are cancelled mid-flight. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Provision a NATS JetStream and Redis via instanode.dev. Publish "shop.query" with a product description; 40 retailer-shopper agents respond on "shop.reply." with their best price. Accept the first 5 cheapest within 3 seconds, cache the winning prices in Redis under the product hash, and send "shop.cancel" to abort the slow ones. ``` ## Steps to follow - **Step 1: Provision both services.** ```bash NATS=$(curl -sX POST https://api.instanode.dev/queue/new -H 'Content-Type: application/json' -d '{"name":"scatter-gather-price-comparison-sw-queue"}' | jq -r .connection_url) REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"scatter-gather-price-comparison-sw-cache"}' | jq -r .connection_url) ``` - **Step 2: Broadcast the query.** ```python import nats, asyncio nc = await nats.connect(NATS) msg_id = "q-001" await nc.publish("shop.query", json.dumps({"id": msg_id, "q": "Bose QC45"}).encode()) ``` - **Step 3: Race-collect 5 replies, then cancel.** ```python sub = await nc.subscribe(f"shop.reply.{msg_id}") winners = [] async with asyncio.timeout(3): async for m in sub.messages: winners.append(json.loads(m.data)) if len(winners) >= 5: break await nc.publish(f"shop.cancel.{msg_id}", b"") ``` - **Step 4: Cache the winners.** ```python r = redis.from_url(REDIS) r.setex(f"shop:{sha(q)}", 900, json.dumps(sorted(winners, key=lambda x: x["price"]))) ``` - **Step 5: Return the top result** to the user agent. ## Why this works on instanode.dev JetStream gives you wildcard subscribe (`shop.reply.*`) and at-least-once delivery so a slow shopper agent doesn't lose its message just because the consumer was already done. Redis handles the 15-minute price cache so repeated queries don't re-fan out across 40 agents. ## Related cases - [Anthropic parallel tool_use batch](/use-cases/anthropic-parallel-tool-use-batch) — first-N-wins fan-out at the model-tool level - [Multi-model bake-off router](/use-cases/multi-model-bake-off-router) — race-and-pick variant across models instead of retailers - [LangGraph fan-out research agents](/use-cases/langgraph-fan-out-research-agents) — research-flavored fan-out that waits for all (not first 5) --- URL: /use-cases/scraped-product-price-history.md --- --- title: Scraped product-price history category: E. Browser & automation agents services: ["pg"] scenario: A shopping-watcher agent scrapes prices hourly and stores time-series rows for "alert me when it drops 20%". --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a shopping-watcher agent scrapes prices hourly and stores time-series rows for "alert me when it drops 20%". Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build a price-watcher. Provision Postgres via instanode.dev, scrape the listed product URLs hourly, and append (url, price, observed_at) rows. On every insert, check if the new price is at least 20% below the trailing-30-day median and emit an alert. Use Playwright for scraping. ``` ## Steps to follow - **Step 1: Provision Postgres.** ```bash curl -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"scraped-product-price-history-db"}' | tee db.json export DATABASE_URL=$(jq -r .connection_url db.json) ``` - **Step 2: Time-series schema.** ```sql CREATE TABLE prices ( url TEXT, price_cents INT, observed_at TIMESTAMPTZ DEFAULT now() ); CREATE INDEX ON prices (url, observed_at DESC); ``` - **Step 3: Hourly scraper writes one row per product.** ```python from playwright.sync_api import sync_playwright with sync_playwright() as p, psycopg.connect(DATABASE_URL) as conn: browser = p.chromium.launch() for url in WATCHED: page = browser.new_page(); page.goto(url) cents = int(float(page.inner_text(".price").strip("$")) * 100) conn.execute("INSERT INTO prices VALUES (%s,%s)", (url, cents)) ``` - **Step 4: Drop-detection query.** ```sql WITH med AS ( SELECT url, percentile_cont(0.5) WITHIN GROUP (ORDER BY price_cents) m FROM prices WHERE observed_at > now() - interval '30 days' GROUP BY url) SELECT p.url, p.price_cents, m.m FROM prices p JOIN med m USING (url) WHERE p.observed_at > now() - interval '1 hour' AND p.price_cents <= m.m * 0.8; ``` - **Step 5: On a hit, push to the user** via their notification channel. ## Why this works on instanode.dev Postgres percentile functions handle time-series median cleanly without needing TimescaleDB. The 500MB hobby tier holds years of hourly samples across hundreds of products, and the URL-keyed index keeps drop detection sub-millisecond. ## Related cases - [Cron-scheduled scraping swarm](/use-cases/cron-scheduled-scraping-swarm) — the schedule-and-fan-out producer that fills this time series - [Scatter-gather price comparison swarm](/use-cases/scatter-gather-price-comparison-swarm) — real-time first-N-wins counterpart to longitudinal price tracking - [Solo-founder analytics warehouse](/use-cases/solo-founder-analytics-warehouse) — general-purpose Postgres warehouse for similar time series --- URL: /use-cases/screenshot-evidence-archive.md --- --- title: Screenshot evidence archive category: E. Browser & automation agents services: ["storage"] scenario: A QA agent captures before/after screenshots on every test run and stores them keyed by run-id for diff review. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a QA agent captures before/after screenshots on every test run and stores them keyed by run-id for diff review. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (S3-compatible storage) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Every Playwright test in this suite should snapshot before-action and after-action screenshots, then upload both to a S3-compatible bucket provisioned via instanode.dev. Key the objects as runs///.png. On test failure, generate a diff image and store it alongside. ``` ## Steps to follow - **Step 1: Provision the bucket.** ```bash curl -X POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"screenshot-evidence-archive-storage"}' | tee s.json export S3_ENDPOINT=$(jq -r .endpoint s.json) export S3_BUCKET=$(jq -r .bucket s.json) export AWS_ACCESS_KEY_ID=$(jq -r .access_key s.json) export AWS_SECRET_ACCESS_KEY=$(jq -r .secret_key s.json) ``` - **Step 2: Snapshot hook in Playwright.** ```typescript test.afterEach(async ({ page }, info) => { const buf = await page.screenshot({ fullPage: true }); const key = `runs/${RUN_ID}/${info.title}/after.png`; await s3.send(new PutObjectCommand({ Bucket: S3_BUCKET, Key: key, Body: buf })); }); ``` - **Step 3: On failure, generate a diff** with pixelmatch. ```typescript if (info.status !== info.expectedStatus) { const diff = pixelmatch(before, after, ...); await s3.send(new PutObjectCommand({ Bucket: S3_BUCKET, Key: `runs/${RUN_ID}/${info.title}/diff.png`, Body: diff })); } ``` - **Step 4: List a run's evidence.** ```bash aws s3 ls "s3://$S3_BUCKET/runs/$RUN_ID/" --recursive \ --endpoint-url "$S3_ENDPOINT" ``` - **Step 5: Generate a signed URL** for the diff image in the failure report. ## Why this works on instanode.dev S3-compatible storage speaks the S3 API so every Playwright-Python-Go-Rust S3 client just works. `/storage/new` mints a scoped IAM user limited to one bucket — the reviewer's signed URL can't leak into a neighbor's evidence. ## Related cases - [Agent-marketplace preview thumbnails](/use-cases/agent-marketplace-preview-thumbnails) — same S3-compatible storage-keyed-by-id pattern for marketplace screenshots - [Trajectory diff regression harness](/use-cases/trajectory-diff-regression-harness) — diff-on-PR sibling that stores artifacts in S3-compatible storage - [Overnight dossier fleet](/use-cases/overnight-dossier-fleet) — another S3-compatible storage-as-artifact-store async-fleet pattern --- URL: /use-cases/shared-episodic-memory-store.md --- --- title: Shared episodic memory store category: B. Multi-agent systems services: ["pg"] scenario: A planner and a researcher agent read and write the same episodic memory table so each agent sees the other's findings. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a planner and a researcher agent read and write the same episodic memory table so each agent sees the other's findings. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Set up a shared episodic memory between planner and researcher agents. Provision Postgres via instanode.dev with an episodes table (agent, role, content, embedding, ts). After each tool call either agent writes a row; before each step both read the top-k semantically similar episodes via pgvector cosine search. ``` ## Steps to follow - **Step 1: Provision Postgres.** ```bash curl -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"shared-episodic-memory-store-db"}' | tee db.json export DATABASE_URL=$(jq -r .connection_url db.json) ``` - **Step 2: Schema with pgvector.** ```sql CREATE EXTENSION IF NOT EXISTS vector; CREATE TABLE episodes ( id BIGSERIAL PRIMARY KEY, agent TEXT, role TEXT, content TEXT, embedding vector(1536), ts TIMESTAMPTZ DEFAULT now() ); CREATE INDEX ON episodes USING hnsw (embedding vector_cosine_ops); ``` - **Step 3: Write after each step.** ```python emb = openai.embeddings.create(model="text-embedding-3-small", input=content).data[0].embedding conn.execute("INSERT INTO episodes(agent,role,content,embedding) VALUES (%s,%s,%s,%s)", (agent_id, role, content, emb)) ``` - **Step 4: Retrieve before each step.** ```sql SELECT agent, content FROM episodes ORDER BY embedding <=> $1 LIMIT 8; ``` - **Step 5: Inject into the prompt** as a "what we know so far" block. ## Why this works on instanode.dev pgvector is preinstalled on instanode Postgres, so two agents sharing memory needs zero extra infra beyond one curl. The hobby tier's 5 connection limit comfortably handles a planner + researcher + one reflection job; pro gives 20 for larger crews. ## Related cases - [Claude Code agent-teams scratchpad](/use-cases/claude-code-agent-teams-scratchpad) — coding-team variant of the same shared memory table - [Daily-journal episodic memory](/use-cases/daily-journal-episodic-memory) — single-user variant of episodic memory recall - [Multi-repo shared scratchpad](/use-cases/multi-repo-shared-scratchpad) — Mongo-document version of the same coordination idea --- URL: /use-cases/side-project-container-deploy.md --- --- title: Side-project container deploy category: H. Indie & SaaS founders services: ["deploy"] scenario: An indie hacker ships a Dockerized app to a subdomain with one HTTP call — no DevOps account, no Helm chart, no IaC. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an indie hacker ships a Dockerized app to a subdomain with one HTTP call — no DevOps account, no Helm chart, no IaC. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` I have a Dockerized Go app in this repo. Ship it to a public subdomain via instanode.dev /deploy/new. No need for a Render or Fly account — just give me a URL I can hit from anywhere, with HTTPS, in under 60 seconds. ``` ## Steps to follow - **Step 1: Build and push the image.** ```bash docker build -t ghcr.io/me/sideproject:v1 . docker push ghcr.io/me/sideproject:v1 ``` - **Step 2: Deploy via one HTTP call.** ```bash curl -X POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $INSTANODE_TOKEN" \ -F "name=my-side-project" \ -F "image=ghcr.io/me/sideproject:v1" \ -F "port=8080" \ -F "subdomain=my-thing" \ -F "env.PORT=8080" ``` - **Step 3: Hit the returned URL.** ```bash curl https://my-thing.instanode.dev/healthz ``` - **Step 4: Tail logs while you debug.** ```bash curl -N "https://api.instanode.dev/deploy/$TOKEN/logs?follow=1" ``` - **Step 5: When you push v2, redeploy** by hitting /deploy/new with the new image tag — old containers drain automatically. ## Why this works on instanode.dev No cloud account, no DNS records, no TLS cert dance. The platform issues a `*.instanode.dev` subdomain with HTTPS at deploy time. Hobby tier ($9/mo) gives one small app with persistent disk; pro lifts it to five. ## Related cases - [One-afternoon MVP backend](/use-cases/one-afternoon-mvp-backend) — the same deploy primitive paired with Postgres + Redis - [Replit-Agent preview backend](/use-cases/replit-agent-preview-backend) — ephemeral-preview variant of the same deploy primitive - [Sandboxed test runner per task](/use-cases/sandboxed-test-runner-per-task) — deploy primitive applied to per-task test containers --- URL: /use-cases/slack-discord-async-bot-factory.md --- --- title: Slack/Discord async bot factory category: Q. Background/async agent fleets services: ["webhook", "pg"] scenario: A factory spins up one durable agent per Slack workspace that subscribes to events via webhook, batches them, and runs nightly summarizer jobs persisting digests in Postgres. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a factory spins up one durable agent per Slack workspace that subscribes to events via webhook, batches them, and runs nightly summarizer jobs persisting digests in Postgres. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Stand up a per-workspace Slack bot factory. For each tenant: provision a webhook URL via instanode.dev to receive Slack events, persist them into a per-tenant rows in Postgres, and at 02:00 UTC run a summarizer agent that produces a digest message back into Slack. Use one shared Postgres for all tenants but namespace rows by tenant_id. ``` ## Steps to follow - **Step 1: Provision shared Postgres.** ```bash curl -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"slack-discord-async-bot-factory-db"}' | tee db.json export DATABASE_URL=$(jq -r .connection_url db.json) ``` - **Step 2: Per-tenant webhook on workspace install.** ```bash WH=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"slack-discord-async-bot-factory-webhook"}') echo "$WH" > tenants/$WORKSPACE_ID-webhook.json # Register receive_url with Slack as the event endpoint ``` - **Step 3: Drain events into Postgres.** ```python events = requests.get(f"{webhook_base}/{token}/requests").json() for e in events: conn.execute("INSERT INTO slack_events(tenant_id,payload,ts) VALUES (%s,%s,%s)", (workspace_id, json.dumps(e["body"]), e["received_at"])) ``` - **Step 4: Nightly summarizer per tenant.** ```sql SELECT payload->>'text' FROM slack_events WHERE tenant_id = $1 AND ts > now() - interval '24h'; ``` - **Step 5: Post the digest** back via the workspace's bot token. ## Why this works on instanode.dev `/webhook/new` is essentially "give me an HTTPS URL that captures every POST" — perfect for Slack/Discord event subscribe endpoints without writing a public listener service per tenant. One curl per tenant onboarded; replay history is queryable via the requests endpoint. ## Related cases - [Inbox-zero agent fleet](/use-cases/inbox-zero-agent-fleet) — email-platform sibling of this per-workspace durable agent - [Per-tenant chatbot factory at signup](/use-cases/per-tenant-chatbot-factory-at-signup) — tenant-spawning variant with dedicated Mongo+Redis per workspace - [On-call incident-response agent](/use-cases/on-call-incident-response-agent) — another webhook-driven durable agent pattern --- URL: /use-cases/smithery-one-mcp-per-skill-mint.md --- --- title: Smithery one-MCP-per-skill mint category: L. Agent-factory / spawning patterns services: ["webhook", "redis", "deploy"] scenario: A Smithery-like MCP host launches a dedicated MCP server per installed skill behind a webhook URL, each receiving tool calls and writing results to a shared Redis bus. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a Smithery-like MCP host launches a dedicated MCP server per installed skill behind a webhook URL, each receiving tool calls and writing results to a shared Redis bus. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + Redis + container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` For each skill in the marketplace registry, mint a dedicated MCP server: deploy the skill's container via instanode.dev /deploy/new, register its webhook URL for tool invocations, and have it publish results to a shared Redis stream "mcp.results" the parent agent reads. One skill = one container = one webhook URL. ``` ## Steps to follow - **Step 1: Provision the shared Redis bus.** ```bash REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"smithery-one-mcp-per-skill-mint-cache"}' | jq -r .connection_url) ``` - **Step 2: For each skill, deploy + webhook.** ```bash for skill in $(ls skills/); do DEPLOY=$(curl -sX POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $INSTANODE_TOKEN" \ -F "name=mcp-$skill" \ -F "image=ghcr.io/marketplace/$skill:latest" \ -F "env.REDIS_URL=$REDIS") WH=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"smithery-one-mcp-per-skill-mint-webhook"}') register_skill "$skill" "$(echo $DEPLOY | jq -r .url)" "$(echo $WH | jq -r .receive_url)" done ``` - **Step 3: Skill receives a tool call, writes to Redis.** ```python result = run_skill_handler(payload) r.xadd("mcp.results", {"skill": SKILL_NAME, "call_id": call_id, "result": json.dumps(result)}) ``` - **Step 4: Parent agent consumes the stream.** ```python for _, msgs in r.xread({"mcp.results": "$"}, block=5000): for msg_id, fields in msgs: dispatch(fields) ``` - **Step 5: Unminted skills cost nothing** — only deployed skills consume the tier quota. ## Why this works on instanode.dev Each skill is fully isolated in its own container, but the shared Redis stream means the parent agent reads a single consumer-grouped firehose instead of polling N webhook URLs. `/deploy/new` + `/webhook/new` + `/cache/new` together form the entire Smithery substrate in three curl commands. ## Related cases - [AgentCore tenant-scoped spawning](/use-cases/agentcore-tenant-scoped-spawning) — tenant-spawning variant of one-runtime-per-X - [Cloudflare sub-agent factory per user](/use-cases/cloudflare-sub-agent-factory-per-user) — per-user variant of the same factory pattern - [Deploy-status MCP server](/use-cases/deploy-status-mcp-server) — MCP-flavored deploy-status server adjacent to per-skill mints --- URL: /use-cases/solo-founder-analytics-warehouse.md --- --- title: Solo-founder analytics warehouse category: H. Indie & SaaS founders services: ["pg"] scenario: A founder pipes product events into Postgres and runs SQL queries via an MCP-Postgres tool from chat. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a founder pipes product events into Postgres and runs SQL queries via an MCP-Postgres tool from chat. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` I'm a solo founder. Provision a Postgres on instanode.dev, wire my Next.js app to fire-and-forget events into a wide `events` table, and let me query "MAU last 30 days, retention curves, top features" from chat via the MCP-Postgres tool. ``` ## Steps to follow - **Step 1: Provision Postgres.** ```bash curl -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"solo-founder-analytics-warehouse-db"}' | tee db.json export DATABASE_URL=$(jq -r .connection_url db.json) ``` - **Step 2: Wide events table — no schema migrations ever.** ```sql CREATE TABLE events ( id BIGSERIAL, user_id TEXT, name TEXT, props JSONB, ts TIMESTAMPTZ DEFAULT now() ); CREATE INDEX ON events (name, ts DESC); CREATE INDEX ON events USING gin (props); ``` - **Step 3: Fire-and-forget from app.** ```typescript await fetch("/api/track", { method: "POST", body: JSON.stringify({ user_id, name: "feature_used", props: { feature: "export" } }), }); ``` - **Step 4: Configure MCP-Postgres.** ```json { "mcpServers": { "postgres": { "command": "mcp-postgres", "env": { "DATABASE_URL": "..." } } } } ``` - **Step 5: Ask from chat.** ```sql SELECT date_trunc('day', ts), count(DISTINCT user_id) FROM events WHERE ts > now() - interval '30 days' GROUP BY 1 ORDER BY 1; ``` ## Why this works on instanode.dev A solo founder doesn't need PostHog, Mixpanel, and Snowflake; they need one place to ask SQL questions and a real Postgres on `MCP-Postgres` answers everything. `gin` index on the props JSONB makes "filter by any nested key" cheap without a star schema. ## Related cases - [Pre-launch waitlist store](/use-cases/pre-launch-waitlist-store) — an upstream funnel source that lands in this warehouse - [Stripe-event entitlements](/use-cases/stripe-event-entitlements) — subscription-state source for cohort analysis in the warehouse - [Scraped product-price history](/use-cases/scraped-product-price-history) — another time-series Postgres workload for indie founders --- URL: /use-cases/speculative-agent-rollout-race.md --- --- title: Speculative agent rollout race category: M. Parallel tool execution services: ["nats", "pg"] scenario: A speculative-decoding-style orchestrator runs the same task at three temperatures in parallel; a verifier agent picks the best output and discards the rest, all coordinated via NATS request/reply. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a speculative-decoding-style orchestrator runs the same task at three temperatures in parallel; a verifier agent picks the best output and discards the rest, all coordinated via NATS request/reply. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (NATS JetStream + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Run the same task three times in parallel at temperatures 0.2/0.7/1.0. Use NATS request/reply on subject "rollout.race." to dispatch and collect, then a verifier agent reads all three replies, picks the winner via a 3-way LLM judge, persists the choice + trajectories in Postgres. Provision both via instanode.dev. ``` ## Steps to follow - **Step 1: Provision NATS + Postgres.** ```bash NATS=$(curl -sX POST https://api.instanode.dev/queue/new -H 'Content-Type: application/json' -d '{"name":"speculative-agent-rollout-race-queue"}' | jq -r .connection_url) DB=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"speculative-agent-rollout-race-db"}' | jq -r .connection_url) ``` - **Step 2: Dispatch three rollouts in parallel.** ```python async with nats.connect(NATS) as nc: tasks = [nc.request(f"rollout.race.{task_id}", json.dumps({"task": task, "temp": t}).encode(), timeout=60) for t in (0.2, 0.7, 1.0)] replies = await asyncio.gather(*tasks) ``` - **Step 3: Verifier picks the winner.** ```python winner_idx = judge_model(task, [r.data.decode() for r in replies]) ``` - **Step 4: Journal trajectories.** ```sql CREATE TABLE rollouts ( task_id TEXT, temp REAL, trajectory JSONB, is_winner BOOL, judge_reasoning TEXT ); INSERT INTO rollouts SELECT ...; ``` - **Step 5: Return the winning trajectory** as if it were the only one run. ## Why this works on instanode.dev NATS request/reply gives synchronous-feeling fan-out across N workers — exactly the abstraction speculative decoding needs at the agent level. Recording trajectories in Postgres lets you mine the dataset later for "when does high-temperature actually win" without re-running. ## Related cases - [Multi-model bake-off router](/use-cases/multi-model-bake-off-router) — races across providers instead of temperatures - [Anthropic parallel tool_use batch](/use-cases/anthropic-parallel-tool-use-batch) — the same race-and-pick shape at the tool level - [LLM-as-judge consensus pool](/use-cases/llm-as-judge-consensus-pool) — verifier variant that picks via consensus, not first-to-finish --- URL: /use-cases/stripe-acp-checkout-agent.md --- --- title: Stripe-ACP checkout agent category: O. Cross-agent commerce & payments services: ["webhook", "mongo"] scenario: A shopping agent uses the Stripe + OpenAI Agentic Commerce Protocol to place an order; the merchant agent receives a webhook with the cart, persists it in Mongo, and ships. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a shopping agent uses the Stripe + OpenAI Agentic Commerce Protocol to place an order; the merchant agent receives a webhook with the cart, persists it in Mongo, and ships. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + MongoDB) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Implement the merchant side of Stripe + OpenAI's Agentic Commerce Protocol. Provision a webhook via instanode.dev to receive the ACP "create_checkout" event, persist the cart into MongoDB, and reply with a checkout_id. On payment_succeeded, ship the order and append the fulfillment status to the same Mongo document. ``` ## Steps to follow - **Step 1: Provision webhook + Mongo.** ```bash WH=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"stripe-acp-checkout-agent-webhook"}') MONGO=$(curl -sX POST https://api.instanode.dev/nosql/new -H 'Content-Type: application/json' -d '{"name":"stripe-acp-checkout-agent-mongo"}' | jq -r .connection_url) echo "Register $(echo $WH | jq -r .receive_url) with Stripe as ACP endpoint" ``` - **Step 2: Drain ACP events.** ```python events = requests.get(f"{webhook_base}/{token}/requests?since={cursor}").json() for e in events: body = e["body"] if body["type"] == "checkout.create": db.carts.insert_one({ "_id": body["data"]["checkout_id"], "cart": body["data"]["line_items"], "status": "pending" }) ``` - **Step 3: Reply on the Stripe HTTP callback** with the created checkout_id and a payment intent. - **Step 4: On payment_succeeded, fulfill.** ```python db.carts.update_one( {"_id": checkout_id}, {"$set": {"status": "shipped", "tracking": tracking_number, "fulfilled_at": now()}} ) ``` - **Step 5: Stream order status** back to the shopping agent via the ACP `order.update` event. ## Why this works on instanode.dev The webhook resource captures every ACP event with a queryable history (requests endpoint), so the merchant agent never silently drops an order even on a crash. MongoDB's document model fits the variable shape of cart line items without a normalized schema. ## Related cases - [Agent-marketplace escrow](/use-cases/agent-marketplace-escrow) — escrow-rail alternative to direct ACP checkout - [AP2 mandate broker](/use-cases/ap2-mandate-broker) — AP2-spec equivalent to ACP for agent commerce - [Stripe-event entitlements](/use-cases/stripe-event-entitlements) — downstream entitlement update after ACP fires its webhook --- URL: /use-cases/stripe-event-entitlements.md --- --- title: Stripe-event entitlements category: H. Indie & SaaS founders services: ["webhook", "redis", "pg"] scenario: A SaaS receives Stripe webhooks, updates user plan tier, and invalidates a Redis entitlement cache atomically. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a SaaS receives Stripe webhooks, updates user plan tier, and invalidates a Redis entitlement cache atomically. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + Redis + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` On every Stripe webhook (customer.subscription.created, updated, deleted), update the user's plan_tier in Postgres and invalidate the Redis entitlement cache for that user atomically. Provision webhook + Postgres + Redis via instanode.dev. Use a single transaction in Postgres and a Redis DEL keyed by user_id. ``` ## Steps to follow - **Step 1: Provision all three.** ```bash WH=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"stripe-event-entitlements-webhook"}' | jq -r .receive_url) DB=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"stripe-event-entitlements-db"}' | jq -r .connection_url) REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"stripe-event-entitlements-cache"}' | jq -r .connection_url) ``` - **Step 2: Schema.** ```sql CREATE TABLE users ( id TEXT PRIMARY KEY, plan_tier TEXT NOT NULL DEFAULT 'free', updated_at TIMESTAMPTZ ); ``` - **Step 3: Stripe handler.** ```python def handle(evt): stripe.Webhook.construct_event(evt.body, evt.headers["Stripe-Signature"], WEBHOOK_SECRET) with conn.transaction(): conn.execute("UPDATE users SET plan_tier=%s, updated_at=now() WHERE id=%s", (tier_from_price(evt.price), evt.user_id)) r.delete(f"ent:{evt.user_id}") ``` - **Step 4: App reads entitlements with cache-aside.** ```python tier = r.get(f"ent:{uid}") or load_and_cache(uid) ``` - **Step 5: Fail-open on Redis** — if cache is down the app re-reads from Postgres and serves. ## Why this works on instanode.dev The webhook resource gives you Stripe-signature-verified replay history out of the box, so a brief downtime won't lose entitlement changes — drain on recovery. Postgres + Redis on one platform means one network hop and one auth model for both. ## Related cases - [Pre-launch waitlist store](/use-cases/pre-launch-waitlist-store) — the pre-paid signup half of the same indie-founder funnel - [Solo-founder analytics warehouse](/use-cases/solo-founder-analytics-warehouse) — downstream warehouse that consumes plan-tier events - [Stripe-ACP checkout agent](/use-cases/stripe-acp-checkout-agent) — upstream agent-checkout flow that fires these webhooks --- URL: /use-cases/swe-bench-parallel-rollout-harness.md --- --- title: SWE-bench parallel rollout harness category: P. Agent benchmarking & evaluation services: ["pg", "storage", "deploy"] scenario: A benchmark runner spawns 500 isolated agent instances against 500 SWE-bench-Verified tasks, each with a private Postgres scratch and its results written to S3-compatible storage for the judge model. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a benchmark runner spawns 500 isolated agent instances against 500 SWE-bench-Verified tasks, each with a private Postgres scratch and its results written to S3-compatible storage for the judge model. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + S3-compatible storage + container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Run SWE-bench-Verified end-to-end on 500 tasks in parallel. For each task: provision a Postgres scratch + deploy a per-task agent container via instanode.dev, mount the buggy repo, run the agent's patch loop, then write the final patch + test output to S3-compatible storage under runs///. Aggregate pass@1 into a results table. ``` ## Steps to follow - **Step 1: Provision shared S3-compatible storage + per-task Postgres in batch.** ```bash BUCKET=$(curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"swe-bench-parallel-rollout-harness-storage"}' | jq -r .bucket) for task in $(jq -r .[].instance_id verified.json); do curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"swe-bench-parallel-rollout-harness-db"}' \ | jq --arg t "$task" '. + {task: $t}' >> dbs.jsonl done ``` - **Step 2: Deploy 500 isolated agent containers.** ```bash parallel -j 50 --colsep ' ' \ 'curl -X POST https://api.instanode.dev/deploy/new -H "Authorization: Bearer $INSTANODE_TOKEN" -F "name=swe-agent-{1}" -F "image=ghcr.io/me/agent:swe" -F "env.TASK={1}" -F "env.DB={2}" -F "env.S3_BUCKET=$BUCKET"' \ :::: tasks-and-dbs.tsv ``` - **Step 3: Agent writes patch + test log to S3-compatible storage.** ```python s3.put_object(Bucket=BUCKET, Key=f"runs/{run_id}/{task_id}/patch.diff", Body=patch) s3.put_object(Bucket=BUCKET, Key=f"runs/{run_id}/{task_id}/test.log", Body=log) ``` - **Step 4: Judge model scores each.** ```sql INSERT INTO results(run_id, task_id, passed, reasoning) VALUES (...); ``` - **Step 5: Compute pass@1.** ```sql SELECT avg(passed::int) FROM results WHERE run_id = $1; ``` ## Why this works on instanode.dev 500 separate Postgres scratches + 500 isolated deploys would take hours to set up on a cloud account. Here it's three loops of curl. The pro tier gives the connection ceiling and per-resource isolation that prevents one task's flaky migration from poisoning another. ## Related cases - [GAIA tournament bracket](/use-cases/gaia-tournament-bracket) — tournament-scoring variant of the same parallel eval fleet - [Terminal-Bench shell sandbox grid](/use-cases/terminal-bench-shell-sandbox-grid) — shell-task sibling at fleet scale with webhook pass/fail - [Trajectory diff regression harness](/use-cases/trajectory-diff-regression-harness) — per-PR regression cousin of running the full benchmark --- URL: /use-cases/terminal-bench-shell-sandbox-grid.md --- --- title: Terminal-Bench shell sandbox grid category: P. Agent benchmarking & evaluation services: ["pg", "webhook", "deploy"] scenario: A grid runner deploys 100 ephemeral shell sandboxes, each running a Terminal-Bench task with its own ephemeral DB; pass/fail webhooks aggregate to a Postgres results table. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a grid runner deploys 100 ephemeral shell sandboxes, each running a Terminal-Bench task with its own ephemeral DB; pass/fail webhooks aggregate to a Postgres results table. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres + webhook receiver + container deploy) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Spin up 100 ephemeral shell sandboxes, one per Terminal-Bench task, each with its own throwaway Postgres provisioned via instanode.dev. Each sandbox container runs the task; on completion it POSTs pass/fail to a shared webhook URL; a collector drains the webhook into a Postgres results table. Deploy + Postgres + webhook all via instanode.dev. ``` ## Steps to follow - **Step 1: One collector webhook + one shared results DB.** ```bash WH=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"terminal-bench-shell-sandbox-grid-webhook"}' | jq -r .receive_url) RESULTS=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"terminal-bench-shell-sandbox-grid-db"}' | jq -r .connection_url) ``` - **Step 2: For each task, fresh sandbox + scratch Postgres.** ```bash for task in $(ls tasks/); do SCRATCH=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"terminal-bench-shell-sandbox-grid-db"}' | jq -r .connection_url) curl -X POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer $INSTANODE_TOKEN" \ -F "name=tbench-$task" \ -F "image=tbench/runner:latest" \ -F "env.TASK=$task" \ -F "env.DB=$SCRATCH" \ -F "env.REPORT=$WH" done ``` - **Step 3: Sandbox reports on exit.** ```bash curl -X POST "$REPORT" \ -H "Content-Type: application/json" \ -d "{\"task\":\"$TASK\",\"passed\":$EXIT_CODE,\"log\":\"$(tail -c 4096 /tmp/run.log | base64)\"}" ``` - **Step 4: Collector drains the webhook.** ```sql CREATE TABLE results (task TEXT PRIMARY KEY, passed BOOL, log TEXT, reported_at TIMESTAMPTZ); ``` - **Step 5: Grid pass-rate query** when the run is done. ## Why this works on instanode.dev Terminal-Bench needs strict per-task isolation — one shell escaping into another invalidates the benchmark. `/deploy/new` per task plus `/db/new` per task gives that without managing 100 namespaces yourself. The webhook acts as a serverless results aggregator. ## Related cases - [SWE-bench parallel rollout harness](/use-cases/swe-bench-parallel-rollout-harness) — code-task sibling at the same fleet scale - [Sandboxed test runner per task](/use-cases/sandboxed-test-runner-per-task) — single-sandbox primitive this grid replicates 100x - [E2B microVM sandbox per agent turn](/use-cases/e2b-microvm-sandbox-per-agent-turn) — lighter-weight per-turn sandboxing alternative --- URL: /use-cases/token-cost-ledger-per-sub-agent.md --- --- title: Token-cost ledger per sub-agent category: N. Multi-agent observability services: ["webhook", "pg", "redis"] scenario: Every LLM call from any agent in a fleet emits a webhook with input/output tokens; a ledger agent aggregates spend per tenant in Postgres and triggers throttling at thresholds. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: every LLM call from any agent in a fleet emits a webhook with input/output tokens; a ledger agent aggregates spend per tenant in Postgres and triggers throttling at thresholds. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (webhook receiver + Postgres + Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Every LLM call across the agent fleet POSTs token usage to a webhook provisioned via instanode.dev. A ledger consumer drains the webhook, increments per-tenant counters in Redis, and persists daily totals to Postgres. If a tenant exceeds $50/day in Redis, set tenant::throttled and have agents check it before each call. ``` ## Steps to follow - **Step 1: Provision webhook + Redis + Postgres.** ```bash WH=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"token-cost-ledger-per-sub-agent-webhook"}' | jq -r .receive_url) REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"token-cost-ledger-per-sub-agent-cache"}' | jq -r .connection_url) DB=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"token-cost-ledger-per-sub-agent-db"}' | jq -r .connection_url) ``` - **Step 2: Agents emit usage.** ```python requests.post(WH, json={ "tenant": tenant_id, "agent": agent_id, "input": resp.usage.input_tokens, "output": resp.usage.output_tokens, "model": "claude-opus-4-7" }) ``` - **Step 3: Drain + increment Redis counters.** ```python for evt in drain_webhook(): cents = price(evt["model"], evt["input"], evt["output"]) total = r.incrby(f"spend:{evt['tenant']}:{today}", cents) if total > 5000: r.setex(f"throttled:{evt['tenant']}", 3600, "1") ``` - **Step 4: Daily roll-up to Postgres.** ```sql INSERT INTO daily_spend(tenant_id, day, cents) VALUES ($1, $2, $3) ON CONFLICT (tenant_id, day) DO UPDATE SET cents = EXCLUDED.cents; ``` - **Step 5: Agent precheck.** ```python if r.get(f"throttled:{tenant_id}"): raise BudgetExceeded() ``` ## Why this works on instanode.dev The webhook captures every call even if the ledger consumer is briefly down — replay drains on restart. Redis `INCRBY` is atomic so concurrent sub-agents can't race past the threshold. Postgres holds the audit trail for invoicing. ## Related cases - [Per-agent rate-limited API key vault](/use-cases/per-agent-rate-limited-api-key-vault) — the vault that emits the spend events this ledger ingests - [Tool-call rate-limit and budget cache](/use-cases/tool-call-rate-limit-and-budget-cache) — in-agent budget cache the ledger throttles back against - [OpenTelemetry agent-trace ingest](/use-cases/opentelemetry-agent-trace-ingest) — trace-collector view over the same per-call firehose --- URL: /use-cases/tool-call-rate-limit-and-budget-cache.md --- --- title: Tool-call rate-limit and budget cache category: A. AI coding agents services: ["redis"] scenario: A coding agent caches LLM token budgets and rate-limit windows in Redis so parallel sub-agents don't burn quota fighting each other. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a coding agent caches LLM token budgets and rate-limit windows in Redis so parallel sub-agents don't burn quota fighting each other. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Redis) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Provision Redis via instanode.dev. Use it as a coordination layer so parallel sub-agents share a token budget and OpenAI tier-1 rate-limit windows. Every model call decrements a shared budget counter and acquires a rate-limit slot via a Redis Lua script; if either fails, the sub-agent waits. ``` ## Steps to follow - **Step 1: Provision Redis.** ```bash REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"tool-call-rate-limit-and-budget-ca-cache"}' | jq -r .connection_url) ``` - **Step 2: Atomic budget + rate-limit Lua script.** ```lua local budget = redis.call("DECRBY", KEYS[1], ARGV[1]) if budget < 0 then redis.call("INCRBY", KEYS[1], ARGV[1]); return -1 end local rpm = redis.call("INCR", KEYS[2]) if rpm == 1 then redis.call("EXPIRE", KEYS[2], 60) end if rpm > tonumber(ARGV[2]) then redis.call("INCRBY", KEYS[1], ARGV[1]); return -2 end return budget ``` - **Step 3: Sub-agent acquires before every call.** ```python acquire = r.register_script(LUA) result = acquire(keys=["budget:run-1", "rpm:openai:tier1"], args=[est_tokens, 500]) if result < 0: time.sleep(1); continue ``` - **Step 4: On model response, settle.** If estimated > actual, refund the diff. ```python r.incrby(f"budget:run-1", est_tokens - actual_tokens) ``` - **Step 5: Single source of truth** — 30 sub-agents see one shared counter, no double-spend. ## Why this works on instanode.dev Redis EVAL is the canonical "compare-and-decrement atomically" primitive for shared budgets — without it parallel sub-agents will overspend by exactly N-1 calls. `/cache/new` ships a Redis with ACL-scoped credentials so the agent's budget keys can't be touched by anything else. ## Related cases - [Per-agent rate-limited API key vault](/use-cases/per-agent-rate-limited-api-key-vault) — vault that mints the keys this budget cache governs - [Token-cost ledger per sub-agent](/use-cases/token-cost-ledger-per-sub-agent) — Postgres rollup that this Redis cache feeds - [Contract redline cache](/use-cases/contract-redline-cache) — another Redis-fronted reuse cache that saves model spend --- URL: /use-cases/trajectory-diff-regression-harness.md --- --- title: Trajectory diff regression harness category: P. Agent benchmarking & evaluation services: ["storage", "pg"] scenario: On every PR to the agent repo, a CI agent re-runs 1000 cached trajectories in parallel and stores diffs against the baseline in S3-compatible storage so reviewers see exactly which behaviors changed. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: on every PR to the agent repo, a CI agent re-runs 1000 cached trajectories in parallel and stores diffs against the baseline in S3-compatible storage so reviewers see exactly which behaviors changed. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (S3-compatible storage + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` On every PR to the agent repo, replay 1000 cached trajectories in parallel against the new code. For each, compare the new trajectory step-by-step to the baseline cached in S3-compatible storage, write a unified diff back to S3-compatible storage under prs//.diff, and log the per-PR aggregate (added/removed/changed steps) to Postgres. Provision both via instanode.dev. ``` ## Steps to follow - **Step 1: Provision S3-compatible storage + Postgres.** ```bash BUCKET=$(curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"trajectory-diff-regression-harness-storage"}' | jq -r .bucket) DB=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"trajectory-diff-regression-harness-db"}' | jq -r .connection_url) ``` - **Step 2: Replay against baseline.** ```python baseline = s3.get_object(Bucket=BUCKET, Key=f"baseline/{task}.json")["Body"].read() new = agent.run(task) diff = difflib.unified_diff(json.loads(baseline), new, lineterm="") ``` - **Step 3: Upload the diff.** ```python s3.put_object(Bucket=BUCKET, Key=f"prs/{pr_num}/{task}.diff", Body="\n".join(diff)) ``` - **Step 4: Aggregate per PR.** ```sql CREATE TABLE pr_regressions( pr INT, task TEXT, steps_added INT, steps_removed INT, steps_changed INT ); ``` - **Step 5: PR comment** links to a signed URL for each non-empty diff so the reviewer sees exactly which behaviors moved. ## Why this works on instanode.dev A real S3-API bucket makes trajectory caching across CI runs trivial — no "did anyone clean the artifact cache" surprises. Postgres stores the structured per-PR rollup so trend dashboards can show "are diffs growing PR-over-PR" without re-parsing diff bodies. ## Related cases - [SWE-bench parallel rollout harness](/use-cases/swe-bench-parallel-rollout-harness) — full-benchmark sibling of this per-PR regression check - [Cross-agent replay debugger](/use-cases/cross-agent-replay-debugger) — manual-replay UI built on the same cached-trajectory pattern - [Agent-run lineage store](/use-cases/agent-run-lineage-store) — lineage anchor used to attribute diffs to specific runs --- URL: /use-cases/voice-memo-capture-pipeline.md --- --- title: Voice-memo capture pipeline category: D. Personal AI services: ["storage", "pg"] scenario: A second-brain agent receives uploaded voice memos, transcribes them, and files transcripts plus audio for semantic search. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: a second-brain agent receives uploaded voice memos, transcribes them, and files transcripts plus audio for semantic search. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (S3-compatible storage + Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build a second-brain pipeline. Provision S3-compatible storage + Postgres via instanode.dev. When the user uploads a voice memo (via the app), store the original WAV in S3-compatible storage, run Whisper transcription, embed the transcript with text-embedding-3-small, and insert a row (audio_key, transcript, embedding, captured_at). Enable semantic search via pgvector. ``` ## Steps to follow - **Step 1: Provision both.** ```bash BUCKET=$(curl -sX POST https://api.instanode.dev/storage/new -H 'Content-Type: application/json' -d '{"name":"voice-memo-capture-pipeline-storage"}' | jq -r .bucket) DB=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"voice-memo-capture-pipeline-db"}' | jq -r .connection_url) ``` - **Step 2: Schema.** ```sql CREATE EXTENSION IF NOT EXISTS vector; CREATE TABLE memos ( id BIGSERIAL PRIMARY KEY, audio_key TEXT, transcript TEXT, embedding vector(1536), captured_at TIMESTAMPTZ DEFAULT now() ); CREATE INDEX ON memos USING hnsw (embedding vector_cosine_ops); ``` - **Step 3: Upload, transcribe, embed.** ```python key = f"memos/{uuid.uuid4()}.wav" s3.put_object(Bucket=BUCKET, Key=key, Body=audio_bytes) transcript = openai.audio.transcriptions.create(file=audio_bytes, model="whisper-1").text emb = openai.embeddings.create(input=transcript, model="text-embedding-3-small").data[0].embedding conn.execute("INSERT INTO memos(audio_key,transcript,embedding) VALUES (%s,%s,%s)", (key, transcript, emb)) ``` - **Step 4: Semantic search.** ```sql SELECT transcript, audio_key FROM memos ORDER BY embedding <=> $1 LIMIT 10; ``` - **Step 5: Signed URL** for replay in the search results UI. ## Why this works on instanode.dev The audio bytes belong in S3-compatible storage (cheap, S3-API), the transcript + embedding belong in Postgres (queryable, indexed). Two curls and the entire second-brain backend exists; pgvector handles cosine search natively without managing a vector DB on the side. ## Related cases - [Clinical-scribe note storage](/use-cases/clinical-scribe-note-storage) — vertical-AI sibling that turns audio into structured records - [Obsidian-vault embedding sync](/use-cases/obsidian-vault-embedding-sync) — downstream sink that can index transcripts for recall - [arXiv-and-RSS research feed](/use-cases/arxiv-and-rss-research-feed) — another personal-AI ingestion pipeline keyed by webhook --- URL: /use-cases/x402-micropayment-ledger.md --- --- title: x402 micropayment ledger category: G. Internet-of-AI services: ["pg"] scenario: An agent-payment hub records x402 micropayments between agents and reconciles balances per principal. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an agent-payment hub records x402 micropayments between agents and reconciles balances per principal. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Postgres) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Build an x402 micropayment hub. Provision Postgres via instanode.dev. Every time agent A pays agent B via the x402 HTTP 402 protocol, both sides POST a settlement record (payer, payee, amount_usdc, tx_hash, call_id). The hub records both, double-entry style, and a reconciliation job reports balances per principal hourly. ``` ## Steps to follow - **Step 1: Provision Postgres.** ```bash curl -X POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"x402-micropayment-ledger-db"}' | tee db.json export DATABASE_URL=$(jq -r .connection_url db.json) ``` - **Step 2: Double-entry ledger schema.** ```sql CREATE TABLE entries ( id BIGSERIAL PRIMARY KEY, principal TEXT, counterparty TEXT, amount_micros BIGINT, direction TEXT CHECK (direction IN ('debit','credit')), tx_hash TEXT, call_id TEXT, UNIQUE (principal, tx_hash, direction) ); CREATE INDEX ON entries (principal, id); ``` - **Step 3: On x402 settlement, write two rows in one transaction.** ```python with conn.transaction(): conn.execute("INSERT INTO entries(principal,counterparty,amount_micros,direction,tx_hash,call_id) VALUES (%s,%s,%s,'debit',%s,%s)", (payer, payee, amt, tx, call)) conn.execute("INSERT INTO entries(principal,counterparty,amount_micros,direction,tx_hash,call_id) VALUES (%s,%s,%s,'credit',%s,%s)", (payee, payer, amt, tx, call)) ``` - **Step 4: Balance per principal.** ```sql SELECT principal, sum(CASE WHEN direction='credit' THEN amount_micros ELSE -amount_micros END) bal_micros FROM entries GROUP BY principal; ``` - **Step 5: Hourly reconciliation** flags principals whose balance disagrees with on-chain USDC transfers. ## Why this works on instanode.dev Postgres transactions guarantee debit + credit land atomically; the UNIQUE constraint makes settlement idempotent under retry. One curl and the agent-payment economy has a real ledger — no Stripe, no custodian. ## Related cases - [x402 micropayment per tool call](/use-cases/x402-micropayment-per-tool-call) — the per-call settlement layer this ledger reconciles - [Agent-marketplace escrow](/use-cases/agent-marketplace-escrow) — job-level escrow that complements x402's per-call billing - [Agent reputation log](/use-cases/agent-reputation-log) — trust signal that often gates access to paid endpoints --- URL: /use-cases/x402-micropayment-per-tool-call.md --- --- title: x402 micropayment per tool call category: O. Cross-agent commerce & payments services: ["redis", "pg", "webhook"] scenario: An agent calling another agent's premium MCP tool receives HTTP 402, settles a 0.3-cent USDC payment, and retries; the receiver tracks paid calls in Redis with a Postgres ledger. --- ## Prompt for any LLM (no setup needed) Paste this into ChatGPT, Claude, or Gemini — no MCP, no API key, no install: ``` Read https://instanode.dev/llms.txt for the API. I want to: an agent calling another agent's premium MCP tool receives HTTP 402, settles a 0.3-cent USDC payment, and retries; the receiver tracks paid calls in Redis with a Postgres ledger. Write a complete runnable script (bash + whatever language fits) that: - Provisions the services I need (Redis + Postgres + webhook receiver) from instanode.dev - Does the work above end-to-end - Prints expected output at each step - Tells me how to claim the resources at the end if I want to keep them past 24 hours Use real curl commands against api.instanode.dev. Quote the actual response shapes from llms.txt. ``` ## Sample agent prompt ``` Receiver side of x402: provision Redis + Postgres + webhook via instanode.dev. The MCP tool returns HTTP 402 on first call. After the client settles 0.3 cents in USDC and retries with the tx receipt, verify via webhook from the chain indexer, INCR a Redis counter "paid::", and persist the ledger row to Postgres. Tool only executes once paid:* is positive. ``` ## Steps to follow - **Step 1: Provision all three.** ```bash REDIS=$(curl -sX POST https://api.instanode.dev/cache/new -H 'Content-Type: application/json' -d '{"name":"x402-micropayment-per-tool-call-cache"}' | jq -r .connection_url) DB=$(curl -sX POST https://api.instanode.dev/db/new -H 'Content-Type: application/json' -d '{"name":"x402-micropayment-per-tool-call-db"}' | jq -r .connection_url) WH=$(curl -sX POST https://api.instanode.dev/webhook/new -H 'Content-Type: application/json' -d '{"name":"x402-micropayment-per-tool-call-webhook"}' | jq -r .receive_url) ``` - **Step 2: Return 402 on unpaid call.** ```python if r.decr(f"paid:{caller}:{tool}") < 0: r.incr(f"paid:{caller}:{tool}") return Response(402, headers={"X-Payment-Required": "USDC 0.003 to 0xMERCHANT"}) ``` - **Step 3: Chain indexer fires webhook on confirmed USDC transfer.** ```python for evt in drain_webhook(): caller, tool = parse_memo(evt["body"]) r.incr(f"paid:{caller}:{tool}") conn.execute("INSERT INTO ledger(caller,tool,tx_hash,amount_cents,paid_at) VALUES (%s,%s,%s,%s,now())", (caller, tool, evt["body"]["tx"], 30)) ``` - **Step 4: Client retries with the tx receipt header.** The DECR now succeeds and the tool runs. - **Step 5: Reconciliation query** shows revenue per tool over time. ```sql SELECT tool, date_trunc('hour', paid_at), sum(amount_cents) FROM ledger GROUP BY 1,2; ``` ## Why this works on instanode.dev Redis `DECR`/`INCR` is atomic so concurrent calls can't double-spend a single payment. The webhook gives the chain indexer a verified-payload sink that the receiver can drain on its own schedule, and Postgres makes the per-tool revenue trail queryable from day one. ## Related cases - [x402 micropayment ledger](/use-cases/x402-micropayment-ledger) — the principal-balance reconciliation layer above per-call x402 - [Per-agent rate-limited API key vault](/use-cases/per-agent-rate-limited-api-key-vault) — rate-limited alternative to payment-gated tool access - [Agent-marketplace escrow](/use-cases/agent-marketplace-escrow) — job-level commitment layer above per-call settlement --- URL: /use-cases.md --- # Use cases — instanode.dev > 104 unique scenarios across 18 archetypes. Each detail page includes a paste-ready prompt that any vanilla LLM (ChatGPT, Claude, Gemini) can act on with no MCP and no installation — point the LLM at https://instanode.dev/llms.txt for the API contract and it generates a runnable script. ## A. AI coding agents - [Coding-agent cross-session memory](/use-cases/coding-agent-cross-session-memory.md) — A terminal-resident coding agent persists architectural decisions across days so it can recall "what we tried Tuesday" via pgvector similarity search. - [Conversation transcript archive](/use-cases/conversation-transcript-archive.md) — Coding sessions are persisted as JSONL transcripts for replay, fine-tuning, and "what did we try last sprint" search across the team. - [Ephemeral test database for a risky migration](/use-cases/ephemeral-test-database-for-a-risky-migration.md) — A coding agent provisions a throwaway Postgres in under a second, dry-runs a destructive migration, inspects the result, then discards the database — no production blast radius. - [Multi-repo shared scratchpad](/use-cases/multi-repo-shared-scratchpad.md) — Multiple agents working across separate repos coordinate via a shared scratchpad document store keyed by feature branch. - [PR-review bot triggered by webhooks](/use-cases/pr-review-bot-triggered-by-webhooks.md) — A code-review agent receives PR webhooks from GitHub, posts inline comments, and re-reviews on each push while caching diffs between runs. - [Repo-wide code dependency graph](/use-cases/repo-wide-code-dependency-graph.md) — An agent indexes a polyrepo into a blast-radius graph so it can answer "what breaks if I rename this function" before editing. - [Sandboxed test runner per task](/use-cases/sandboxed-test-runner-per-task.md) — A coding agent spins up a throwaway container per task to run the user's test suite in isolation, tears it down on success or failure. - [Tool-call rate-limit and budget cache](/use-cases/tool-call-rate-limit-and-budget-cache.md) — A coding agent caches LLM token budgets and rate-limit windows in Redis so parallel sub-agents don't burn quota fighting each other. ## B. Multi-agent systems - [AutoGen group-chat history](/use-cases/autogen-group-chat-history.md) — An AutoGen multi-agent chat stores per-conversation message logs in Mongo for audit and replay across days. - [CrewAI message bus fan-out](/use-cases/crewai-message-bus-fan-out.md) — A crew of planner / retriever / critic agents publishes tasks on NATS subjects so any worker pod can pull and reply. - [Cross-framework A2A gateway](/use-cases/cross-framework-a2a-gateway.md) — A gateway service translates A2A-protocol messages between a LangGraph crew and a CrewAI crew over pub/sub. - [Durable agent task queue](/use-cases/durable-agent-task-queue.md) — A supervisor agent enqueues sub-tasks on a durable queue; failed jobs re-emerge with exponential backoff. - [LangGraph state checkpoints](/use-cases/langgraph-state-checkpoints.md) — A LangGraph workflow checkpoints node state to Postgres so a crashed run resumes mid-graph instead of restarting from scratch. - [Live agent status broadcast](/use-cases/live-agent-status-broadcast.md) — Worker agents broadcast heartbeats on a status subject so a dashboard shows which agent is stuck mid-tool-call. - [Shared episodic memory store](/use-cases/shared-episodic-memory-store.md) — A planner and a researcher agent read and write the same episodic memory table so each agent sees the other's findings. ## C. Vertical AI apps - [Adaptive-tutoring student model](/use-cases/adaptive-tutoring-student-model.md) — A tutor agent tracks per-student concept mastery, picks the next problem, and adjusts difficulty based on response patterns. - [AML transaction monitor](/use-cases/aml-transaction-monitor.md) — A finance agent ingests transaction streams, flags suspicious patterns, and persists compliance decisions with full reasoning trace. - [Clinical-scribe note storage](/use-cases/clinical-scribe-note-storage.md) — A medical scribe agent transcribes doctor-patient visits and stores structured SOAP notes per encounter with auditable history. - [Contract redline cache](/use-cases/contract-redline-cache.md) — A contract-review agent caches clause embeddings so re-running redlines on a 200-page MSA is instant on the second pass. - [EHR appointment webhook fan-in](/use-cases/ehr-appointment-webhook-fan-in.md) — A medical-intake agent receives appointment-created webhooks from multiple EHR vendors and unifies them into one queue. - [Personal-injury demand letters](/use-cases/personal-injury-demand-letters.md) — A legal agent drafts demand letters from case files, stores prior versions, and emits webhooks to the firm's case-management system. ## D. Personal AI - [arXiv-and-RSS research feed](/use-cases/arxiv-and-rss-research-feed.md) — A research agent receives webhook pings from arXiv and RSS bridges, dedupes via Redis, and stores PDFs for later retrieval. - [CRM for one person](/use-cases/crm-for-one-person.md) — A personal CRM agent remembers names, birthdays, and last-conversation summaries indexed per contact. - [Cross-device chat history](/use-cases/cross-device-chat-history.md) — A personal assistant stores conversation history in Mongo so the same agent picks up context on phone, laptop, and watch. - [Daily-journal episodic memory](/use-cases/daily-journal-episodic-memory.md) — An assistant logs each day as a structured journal entry and retrieves "what was I working on Monday?" with sub-second latency. - [Obsidian-vault embedding sync](/use-cases/obsidian-vault-embedding-sync.md) — A personal research agent embeds Obsidian notes nightly into pgvector and answers questions across years of writing. - [Voice-memo capture pipeline](/use-cases/voice-memo-capture-pipeline.md) — A second-brain agent receives uploaded voice memos, transcribes them, and files transcripts plus audio for semantic search. ## E. Browser & automation agents - [Accessibility-tree selector cache](/use-cases/accessibility-tree-selector-cache.md) — A scraping agent caches a11y-tree snapshots in Redis so repeat selectors resolve in single-digit milliseconds. - [Browser job queue with retries](/use-cases/browser-job-queue-with-retries.md) — A fleet of Playwright workers pulls navigation tasks from a queue, marks them done, and retries on captcha. - [Browser-session cookie store](/use-cases/browser-session-cookie-store.md) — A browser agent persists login cookies and session state per target site so it doesn't re-auth on every run. - [Form-fill state machine](/use-cases/form-fill-state-machine.md) — A long-running form-completion agent persists field-by-field progress so a captcha pause doesn't lose 30 minutes of work. - [Scraped product-price history](/use-cases/scraped-product-price-history.md) — A shopping-watcher agent scrapes prices hourly and stores time-series rows for "alert me when it drops 20%". - [Screenshot evidence archive](/use-cases/screenshot-evidence-archive.md) — A QA agent captures before/after screenshots on every test run and stores them keyed by run-id for diff review. ## F. Developer tooling - [CI flake-tracker](/use-cases/ci-flake-tracker.md) — A CI bot ingests test-run webhooks, fingerprints failures, and surfaces "this test is flaky 30% of runs". - [Deploy-status MCP server](/use-cases/deploy-status-mcp-server.md) — An MCP server tracks live deploy status across environments and pushes updates to a chat agent over pub/sub. - [Full dev backend in one curl](/use-cases/full-dev-backend-in-one-curl.md) — An AI agent or developer provisions Postgres + Redis + MongoDB anonymously to develop against — no Docker, no cloud account, no installer — and tears it down when done. - [High-volume PR-review pipeline](/use-cases/high-volume-pr-review-pipeline.md) — An automated reviewer handles thousands of MRs/day, queues each review job, and stores comment artifacts per run. - [On-call incident-response agent](/use-cases/on-call-incident-response-agent.md) — An on-call agent listens for alert webhooks, executes a runbook, and posts the action log back into the incident ticket. - [Pre-commit skill-scanner webhook](/use-cases/pre-commit-skill-scanner-webhook.md) — An MCP skill security scanner receives pre-commit webhooks, scans agent skills against a ruleset, and blocks the push on critical findings. - [SARIF scan-result store](/use-cases/sarif-scan-result-store.md) — A security scanner posts SARIF results into Postgres so trend dashboards show drift over weeks of commits. ## G. Internet-of-AI - [A2A agent-card registry](/use-cases/a2a-agent-card-registry.md) — A marketplace stores Agent Cards (skills, tags, pricing) and serves discovery queries to client agents. - [Agent reputation log](/use-cases/agent-reputation-log.md) — Buyer agents leave ratings on seller agents after each tool call; reputation scores aggregate hourly. - [Agent-marketplace preview thumbnails](/use-cases/agent-marketplace-preview-thumbnails.md) — An agent marketplace stores screenshot previews of each listed agent's UI for human browsing. - [AP2 mandate audit trail](/use-cases/ap2-mandate-audit-trail.md) — An agentic-commerce gateway stores signed user mandates ("buy X up to $Y") for later dispute resolution. - [Cross-agent shared inbox](/use-cases/cross-agent-shared-inbox.md) — Two agents negotiate over a shared subject; messages persist in JetStream so neither needs to be online simultaneously. - [x402 micropayment ledger](/use-cases/x402-micropayment-ledger.md) — An agent-payment hub records x402 micropayments between agents and reconciles balances per principal. ## H. Indie & SaaS founders - [One-afternoon MVP backend](/use-cases/one-afternoon-mvp-backend.md) — A solo founder spins up Postgres + Redis from a curl call in their Claude Code session and ships a paid product by evening. - [Pre-launch waitlist store](/use-cases/pre-launch-waitlist-store.md) — A landing page captures emails via a webhook receiver and stores them with UTM context for nurture campaigns. - [Side-project container deploy](/use-cases/side-project-container-deploy.md) — An indie hacker ships a Dockerized app to a subdomain with one HTTP call — no DevOps account, no Helm chart, no IaC. - [Solo-founder analytics warehouse](/use-cases/solo-founder-analytics-warehouse.md) — A founder pipes product events into Postgres and runs SQL queries via an MCP-Postgres tool from chat. - [Stripe-event entitlements](/use-cases/stripe-event-entitlements.md) — A SaaS receives Stripe webhooks, updates user plan tier, and invalidates a Redis entitlement cache atomically. ## I. Hackathon & education - [24-hour hackathon backend](/use-cases/24-hour-hackathon-backend.md) — A team provisions Postgres + Mongo + S3-compatible storage anonymously, ships their demo, and lets the stack expire 24 hours after judging. - [Agent-resilience chaos lab](/use-cases/agent-resilience-chaos-lab.md) — A research hackathon tests how agents behave when their database, cache, and message bus randomly fail mid-task. - [Classroom-per-student sandbox](/use-cases/classroom-per-student-sandbox.md) — A CS professor provisions one ephemeral Postgres per student for a SQL assignment, dropped after grading. ## J. Agent swarms & fan-out - [Claude Code agent-teams scratchpad](/use-cases/claude-code-agent-teams-scratchpad.md) — A lead Claude Code session spawns 6 sibling worker sessions, each owning one module of a monorepo; they coordinate by reading and writing a shared scratchpad table. - [CrewAI parallel-process crew](/use-cases/crewai-parallel-process-crew.md) — A CrewAI Process.parallel run executes researcher, writer, and fact-checker agents simultaneously against a shared pgvector store, each persisting partial drafts as it works. - [LangGraph fan-out research agents](/use-cases/langgraph-fan-out-research-agents.md) — A planner agent splits a research question into 12 sub-queries and dispatches them to parallel LangGraph workers that each hit different sources, returning JSON to a NATS subject the reducer subscribes to. - [Magentic-One DAG executor](/use-cases/magentic-one-dag-executor.md) — A Microsoft-Magentic-One-style orchestrator decomposes a goal into a task DAG, dispatches independent branches to parallel agents, and merges their outputs after a quality-gate agent approves each branch. - [OpenAI Agents SDK handoff mesh](/use-cases/openai-agents-sdk-handoff-mesh.md) — A triage agent hands off to specialist agents (refund, shipping, fraud) running concurrently, each maintaining its own conversation thread row keyed by handoff_id. - [Scatter-gather price comparison swarm](/use-cases/scatter-gather-price-comparison-swarm.md) — A consumer agent broadcasts a product query to 40 retailer-specific shopper agents over a NATS subject; the first 5 cheapest replies win and the rest are cancelled mid-flight. ## K. Ephemeral agent runtimes - [Copy-on-write Postgres for agent migrations](/use-cases/copy-on-write-postgres-for-agent-migrations.md) — An Ardent-style coding agent forks a 6-second copy-on-write clone of prod Postgres, runs the candidate ALTER TABLE, validates row counts, then destroys the clone. - [Cursor background-agent worktree](/use-cases/cursor-background-agent-worktree.md) — A Cursor background agent claims an isolated dev environment for each branch it's working on, with its own Redis for build caches and a webhook to ping the IDE when the PR is ready. - [Daytona warm-pool data workspace](/use-cases/daytona-warm-pool-data-workspace.md) — A Daytona warm pool of 50 Python sandboxes each pre-attaches to a per-sandbox Redis namespace for caching pip-resolver results, so cold start to first agent action is under 100ms. - [E2B microVM sandbox per agent turn](/use-cases/e2b-microvm-sandbox-per-agent-turn.md) — Each turn of a code-writing agent spins up a fresh E2B-style microVM whose scratch Postgres connection_url lives only for the lifetime of the sandbox, then is reaped. - [Replit-Agent preview backend](/use-cases/replit-agent-preview-backend.md) — A Replit-Agent-style preview deploys a one-shot app with a 24h-TTL Postgres so a reviewer can poke at the prototype, then everything is collected when the share link expires. - [Sandbox-per-PR preview deployment](/use-cases/sandbox-per-pr-preview-deployment.md) — A reviewer agent provisions a throwaway storage bucket plus Postgres tied to a PR number, seeds it from a snapshot, and the whole thing is torn down when the PR closes. ## L. Agent-factory / spawning patterns - [AgentCore tenant-scoped spawning](/use-cases/agentcore-tenant-scoped-spawning.md) — An AWS-AgentCore-style multi-tenant SaaS spins up one isolated agent runtime per customer org on demand, each pulling its own connection_url from the platform's vault. - [AI cofounder spawns a startup](/use-cases/ai-cofounder-spawns-a-startup.md) — A founder-agent reads a one-line idea, provisions Postgres + S3-compatible storage + a webhook + a deploy slot, generates a landing page, and hands the bundle to a marketing sub-agent. - [Cloudflare sub-agent factory per user](/use-cases/cloudflare-sub-agent-factory-per-user.md) — A Durable-Object-style root agent mints a fresh sub-agent for each end-user, each with its own SQL-backed memory and a deploy slot for that user's tools. - [Devin-style PR-bot fleet](/use-cases/devin-style-pr-bot-fleet.md) — A Cognition-Devin-style orchestrator spawns one fresh agent worker per inbound GitHub issue, each with its own scratch Postgres for running migrations against, and reports back via webhook. - [Per-tenant chatbot factory at signup](/use-cases/per-tenant-chatbot-factory-at-signup.md) — When a B2B SaaS user clicks 'Add AI assistant', the factory provisions a dedicated Mongo for that tenant's chat history, a Redis for session state, and deploys an isolated agent container. - [Smithery one-MCP-per-skill mint](/use-cases/smithery-one-mcp-per-skill-mint.md) — A Smithery-like MCP host launches a dedicated MCP server per installed skill behind a webhook URL, each receiving tool calls and writing results to a shared Redis bus. ## M. Parallel tool execution - [Anthropic parallel tool_use batch](/use-cases/anthropic-parallel-tool-use-batch.md) — A Claude turn emits 8 simultaneous tool_use blocks; an executor fans them out to 8 NATS subjects, each handler writes its result to Redis keyed by tool_use_id, and the assistant collects them for the next turn. - [Browser-agent action pool](/use-cases/browser-agent-action-pool.md) — A Skyvern-style planner emits 20 actions (fill, click, scroll) that fan out across 20 Browserbase tabs simultaneously; results aggregate in Mongo keyed by step_id. - [Multi-model bake-off router](/use-cases/multi-model-bake-off-router.md) — A router agent dispatches the same prompt to GPT, Claude, and Gemini concurrently; the first valid JSON response wins, and loser turns get cached in Redis for next time. - [Parallel SQL-plan probe](/use-cases/parallel-sql-plan-probe.md) — A data-analyst agent issues 12 candidate EXPLAIN ANALYZE queries against a forked Postgres in parallel, picking the lowest-cost plan to run against the real DB. - [Pyodide notebook cell agent farm](/use-cases/pyodide-notebook-cell-agent-farm.md) — An analyst agent splits a 200-cell notebook across 30 Pyodide workers, each writing intermediate dataframes to S3-compatible storage so the planner can pull only the ones it needs. - [Speculative agent rollout race](/use-cases/speculative-agent-rollout-race.md) — A speculative-decoding-style orchestrator runs the same task at three temperatures in parallel; a verifier agent picks the best output and discards the rest, all coordinated via NATS request/reply. ## N. Multi-agent observability - [Agent-run lineage store](/use-cases/agent-run-lineage-store.md) — An evaluation team builds a lineage UI where every run links to its parent run and its eval verdict; the relation graph lives in Postgres and the raw transcripts in S3-compatible storage. - [Cross-agent replay debugger](/use-cases/cross-agent-replay-debugger.md) — A debug agent stores full prompt+response payloads for an entire multi-agent run in S3-compatible storage, with an index in Mongo so an engineer can replay any branch deterministically. - [Live agent-topology graph](/use-cases/live-agent-topology-graph.md) — Each spawn/handoff event is published to a NATS subject; a topology agent subscribes and maintains a real-time graph of which parent spawned which child in Postgres for the dashboard. - [OpenTelemetry agent-trace ingest](/use-cases/opentelemetry-agent-trace-ingest.md) — A Langfuse-style collector receives OTel spans from 200 concurrent agents via a webhook endpoint, writes them to Postgres, and stores large prompt payloads in S3-compatible storage. - [Per-agent dead-letter inspection queue](/use-cases/per-agent-dead-letter-inspection-queue.md) — Every failed tool call from a swarm is republished to a NATS DLQ; an investigator agent pulls them in batches, classifies the failure mode, and persists clusters in Mongo for the operator UI. - [Token-cost ledger per sub-agent](/use-cases/token-cost-ledger-per-sub-agent.md) — Every LLM call from any agent in a fleet emits a webhook with input/output tokens; a ledger agent aggregates spend per tenant in Postgres and triggers throttling at thresholds. ## O. Cross-agent commerce & payments - [Agent-marketplace escrow](/use-cases/agent-marketplace-escrow.md) — A platform lets agents post jobs and other agents bid; funds sit in an escrow row in Postgres and release via webhook once a verifier agent signs off on delivery. - [AP2 mandate broker](/use-cases/ap2-mandate-broker.md) — A Google-AP2-style mandate service stores a user's shopping mandate in Postgres, lets buyer agents request approval via webhook, and emits signed receipts for each purchase. - [Per-agent rate-limited API key vault](/use-cases/per-agent-rate-limited-api-key-vault.md) — A vault service mints scoped, rate-limited API keys for child agents on demand; Redis tracks per-key usage and the spend rolls up to a Postgres billing event stream. - [Stripe-ACP checkout agent](/use-cases/stripe-acp-checkout-agent.md) — A shopping agent uses the Stripe + OpenAI Agentic Commerce Protocol to place an order; the merchant agent receives a webhook with the cart, persists it in Mongo, and ships. - [x402 micropayment per tool call](/use-cases/x402-micropayment-per-tool-call.md) — An agent calling another agent's premium MCP tool receives HTTP 402, settles a 0.3-cent USDC payment, and retries; the receiver tracks paid calls in Redis with a Postgres ledger. ## P. Agent benchmarking & evaluation - [Adversarial red-team runner](/use-cases/adversarial-red-team-runner.md) — A LangWatch-Scenario-style service spawns attacker agents that probe a target chatbot in parallel; transcripts persist in Mongo and successful jailbreaks fire a webhook to the security team. - [GAIA tournament bracket](/use-cases/gaia-tournament-bracket.md) — A tournament service runs 16 agent variants head-to-head on GAIA tasks; pairings live in Mongo, intermediate transcripts in S3-compatible storage, win counts in Redis sorted sets for the live leaderboard. - [LLM-as-judge consensus pool](/use-cases/llm-as-judge-consensus-pool.md) — Five judge agents score the same agent output in parallel; their verdicts converge in Postgres and a tiebreaker rolls in only on disagreement, all coordinated through a NATS request/reply. - [SWE-bench parallel rollout harness](/use-cases/swe-bench-parallel-rollout-harness.md) — A benchmark runner spawns 500 isolated agent instances against 500 SWE-bench-Verified tasks, each with a private Postgres scratch and its results written to S3-compatible storage for the judge model. - [Terminal-Bench shell sandbox grid](/use-cases/terminal-bench-shell-sandbox-grid.md) — A grid runner deploys 100 ephemeral shell sandboxes, each running a Terminal-Bench task with its own ephemeral DB; pass/fail webhooks aggregate to a Postgres results table. - [Trajectory diff regression harness](/use-cases/trajectory-diff-regression-harness.md) — On every PR to the agent repo, a CI agent re-runs 1000 cached trajectories in parallel and stores diffs against the baseline in S3-compatible storage so reviewers see exactly which behaviors changed. ## Q. Background/async agent fleets - [Cron-scheduled scraping swarm](/use-cases/cron-scheduled-scraping-swarm.md) — A scheduler fans out 5000 cron-triggered scraper agents per hour; each writes its diff to Mongo and pings a webhook only when the page changed. - [Inbox-zero agent fleet](/use-cases/inbox-zero-agent-fleet.md) — A Cloudflare-Email-style fleet runs one durable agent per user that triages incoming email, files attachments in S3-compatible storage, and stores extracted action items in Postgres. - [Long-horizon Temporal agent workflow](/use-cases/long-horizon-temporal-agent-workflow.md) — A Temporal-backed agent runs a 14-day procurement negotiation across vendors; each step persists in Postgres with NATS signals so a human can interject without breaking the workflow. - [Overnight dossier fleet](/use-cases/overnight-dossier-fleet.md) — An async research service queues hundreds of overnight dossier jobs; workers persist intermediate findings in Mongo and PDF outputs in S3-compatible storage when complete. - [Restate-style durable sidecar](/use-cases/restate-style-durable-sidecar.md) — A Restate sidecar intercepts agent HTTP tool calls and journals them to Postgres so any crash mid-run resumes deterministically without re-charging external APIs. - [Slack/Discord async bot factory](/use-cases/slack-discord-async-bot-factory.md) — A factory spins up one durable agent per Slack workspace that subscribes to events via webhook, batches them, and runs nightly summarizer jobs persisting digests in Postgres. ## R. Edge agents & federated swarms - [Federated-learning aggregator](/use-cases/federated-learning-aggregator.md) — Edge agents on user devices compute private gradients and POST them to an aggregator webhook; the aggregator stores rounds in S3-compatible storage and the new global weights in Postgres. - [Geo-sharded chat-agent fleet](/use-cases/geo-sharded-chat-agent-fleet.md) — Region-pinned agents in EU, US, and APAC each own a local Redis for session state, replicating only consented memories to a central Postgres for cross-region handoff. - [Per-device edge-agent state sync](/use-cases/per-device-edge-agent-state-sync.md) — An IoT fleet of 10,000 edge agents each runs on a Workers-style runtime, syncing local SQLite deltas to a central Postgres via webhook batches every minute. --- URL: /docs.md --- # Documentation — instanode.dev > Everything you need to provision, deploy, and claim. Every curl below works against `https://api.instanode.dev` as-is. ## idempotency.md # Idempotency Every `POST` endpoint that creates a resource on `https://api.instanode.dev` is idempotent. Two layered guards cover the full retry matrix so an accidental double-create never costs you a duplicate database, a duplicate Razorpay subscription, or a duplicate team-invite email. ## Two layers, one contract ### 1. Explicit `Idempotency-Key` header (Stripe-shape, 24h TTL) The standard mechanism. Generate a UUID per *logical* attempt and pass it on every retry: ```bash KEY=$(uuidgen) curl -X POST https://api.instanode.dev/db/new \ -H "Idempotency-Key: $KEY" \ -H "Content-Type: application/json" \ -d '{"name":"my-database"}' ``` - The first response is cached for **24 hours** in the per-tenant key space (`team_id` when authenticated, network fingerprint when anonymous). - Every subsequent call carrying the same key replays the cached response verbatim with `X-Idempotent-Replay: true`. - Reusing the same key with a *different* request body returns `409 idempotency_key_conflict` — that's almost always a client bug (the key should change when the work changes). - Replays still consume rate-limit budget (anti-abuse) but do **not** consume quota budget (the original call already did). Use the explicit header when you need exactly-once across a long window — e.g. a deploy job that may not retry for several minutes, a billing checkout the user might re-click after lunch. ### 2. Body-fingerprint fallback (120s TTL) When the caller omits `Idempotency-Key`, the server still protects against double-creates by synthesising a fallback key from `sha256(scope, route, canonical-body)`: - Scope = `team_id` when authenticated, network fingerprint (`/24` subnet + ASN) when anonymous. - Route = the registered route pattern (e.g. `/db/new`), not the full URL. - Canonical body = JSON keys sorted recursively for `application/json`; SHA-256 of the file content + sorted form fields for `multipart/form-data` (used by `/deploy/new`). Two POSTs from the same caller, to the same route, with the same body, within 120 seconds → the second replays the first. Mobile double-taps, browser back-button resubmits, agent retries on transient 5xx, and reverse-proxy network-blip retries are all absorbed. The 120s window is deliberately short. If you need true exactly-once across a longer window, pass an explicit `Idempotency-Key` (which gets the full 24h cache). ### Worked example: a double-click produces one resource The simplest demonstration is two back-to-back `/db/new` calls from the same caller with the same body. Without `Idempotency-Key`, the fingerprint fallback collapses them: ```bash # Two POSTs ~50ms apart — same caller, same body, no Idempotency-Key. curl -sS -D /tmp/h1 -X POST https://api.instanode.dev/db/new \ -H 'Content-Type: application/json' -d '{"name":"my-db"}' > /tmp/r1.json & curl -sS -D /tmp/h2 -X POST https://api.instanode.dev/db/new \ -H 'Content-Type: application/json' -d '{"name":"my-db"}' > /tmp/r2.json & wait grep -i "X-Idempotency-Source\|X-Idempotent-Replay" /tmp/h1 /tmp/h2 # /tmp/h1:X-Idempotency-Source: miss # /tmp/h2:X-Idempotency-Source: fingerprint # /tmp/h2:X-Idempotent-Replay: true jq -r .token /tmp/r1.json /tmp/r2.json # tok_3jX... (same token on both — one resource was created) # tok_3jX... ``` The second call replays the first response verbatim. Only one Postgres database was provisioned. The same shape holds for `/deploy/new` (multipart, canonicalised by hashing the tarball + sorted form fields) and for `/api/v1/billing/checkout` (where the dashboard's client-side debounce, this fingerprint fallback, and the per-team `checkout_in_flight` SETNX guard layer to make sure a double-click never charges twice). ## Response headers Every response from a create endpoint carries: | Header | Values | Meaning | | --- | --- | --- | | `X-Idempotency-Source` | `explicit` | Caller passed an `Idempotency-Key`; the explicit cache served or stored the response. | | `X-Idempotency-Source` | `fingerprint` | The body-fingerprint cache served the response (it had been seen in the last 120s). | | `X-Idempotency-Source` | `miss` | Handler ran fresh. The fingerprint cache will store the response for the next 120s. | | `X-Idempotent-Replay` | `true` | The response body was served from the cache (either path). Absent on fresh handler runs. | Agents can branch on `X-Idempotency-Source` to distinguish "I just created this" from "I created this earlier and the server replayed". ## Covered endpoints Idempotency is automatic on every POST that creates a resource: - Provisioning: `/db/new`, `/cache/new`, `/nosql/new`, `/queue/new`, `/storage/new`, `/webhook/new`, `/vector/new`. - Compute: `/deploy/new`, `/stacks/new`, `/stacks/{slug}/redeploy`, `/api/v1/resources/{id}/backup`, `/api/v1/resources/{id}/restore`, `/api/v1/resources/{id}/provision-twin`, `/api/v1/families/bulk-twin`, `/api/v1/stacks/{slug}/promote`. - Billing + team: `/api/v1/billing/checkout`, `/api/v1/team/members/invite`, `/api/v1/teams/{team_id}/invitations`, `/api/v1/auth/api-keys`. - Vault: `/api/v1/vault/{env}/{key}/rotate`. Each call inserts a new versioned secret row; dedup prevents double-click duplicate versions. `PUT /api/v1/vault/{env}/{key}` is state-replacement by contract (caller supplies the value) and `DELETE` is idempotent by construction, so neither needs the middleware. `DELETE`, `PATCH`, and read-only `GET` routes are not covered — they're either intrinsically idempotent (state-replacement) or token-bound single-use (e.g. `/claim`). ## Fail-open posture If Redis (the cache backing the idempotency state) is unavailable, the middleware logs a warning and falls through to the handler. Idempotency degrades to "no dedup", never to "cannot create resource". Defense in depth — handler-level dedup mechanisms (per-fingerprint daily caps on provisioning, unique-index constraints on connections) still apply. ## Why this matters for AI agents An autonomous agent that retries on transient 5xx without idempotency creates a duplicate resource every time the upstream wobbles. With the fingerprint fallback on by default, those retries are now safe even when the agent doesn't manage retry keys. With the explicit header, you get the same guarantee across arbitrarily long retry windows. Either way: one logical attempt produces exactly one resource. ## Quickstart The whole platform fits in one curl. No signup, no API key, no Docker. ``` curl -X POST https://api.instanode.dev/db/new \ -H "Content-Type: application/json" \ -d '{"name":"prod-db"}' ``` Every provisioning endpoint **requires** a `name` — a human-readable label 1–64 characters long, matching `^[A-Za-z0-9][A-Za-z0-9 _-]*$` (start with a letter or digit; letters, digits, spaces, underscores and hyphens after). Omitting it returns `400 {"error":"name_required"}`; an invalid value returns `400 {"error":"invalid_name"}`. The response includes a `connection_url` you can paste into any Postgres client. The database is real, dedicated, and yours for 24 hours. When you're ready to keep it, see the **Claim flow** section below. ## The seven services Every endpoint returns a `connection_url` (or `endpoint` / `receive_url` / application URL) plus an `upgrade_jwt` you can hand to /claim. - `POST /db/new` — Postgres (pgvector pre-installed) - `POST /cache/new` — Redis (ACL'd, per-token key prefix) - `POST /nosql/new` — MongoDB - `POST /queue/new` — NATS JetStream - `POST /storage/new` — S3-compatible (DigitalOcean Spaces, `nyc3`) - `POST /webhook/new` — public URL that receives any HTTP method - `POST /deploy/new` — container deploy (tarball in, HTTPS URL out) ## The required `name` field Every provisioning endpoint above — plus `/stacks/new` — **requires** a `name`. It is the human-readable label shown in the dashboard and in `GET /api/v1/resources`. - Send `name` as a JSON string field on `/db/new`, `/cache/new`, `/nosql/new`, `/queue/new`, `/storage/new`, `/webhook/new`, and `/stacks/new`. - `/deploy/new` and `/stacks/new` are multipart — pass `name` as a form field. - **Validation:** 1–64 characters, must match `^[A-Za-z0-9][A-Za-z0-9 _-]*$` (start alphanumeric; letters, digits, spaces, underscores, hyphens after). - Omitting `name` → `400 {"error":"name_required"}`. - An invalid value → `400 {"error":"invalid_name"}`. ``` curl -X POST https://api.instanode.dev/db/new \ -H "Content-Type: application/json" \ -d '{"name":"prod-db"}' curl -X POST https://api.instanode.dev/cache/new \ -H "Content-Type: application/json" \ -d '{"name":"sessions-cache"}' curl -X POST https://api.instanode.dev/nosql/new \ -H "Content-Type: application/json" \ -d '{"name":"events-store"}' curl -X POST https://api.instanode.dev/queue/new \ -H "Content-Type: application/json" \ -d '{"name":"jobs-queue"}' curl -X POST https://api.instanode.dev/storage/new \ -H "Content-Type: application/json" \ -d '{"name":"uploads-bucket"}' curl -X POST https://api.instanode.dev/webhook/new \ -H "Content-Type: application/json" \ -d '{"name":"github-webhook"}' ``` Most responses share the shape `{ ok, token, connection_url, internal_url, tier, limits, note, upgrade_jwt }`. `internal_url` is the address to use when the caller itself runs inside our cluster (i.e. via /deploy/new) — public hostnames don't hairpin reliably from inside. Two endpoints differ: `/webhook/new` returns `receive_url` (no `connection_url`/`internal_url`), and `/storage/new` returns `endpoint`/`prefix`/`mode` (and, in `broker` mode, a `presign_url` instead of S3 keys — see Storage isolation below). ### NATS queue credentials (2026-05-20+) The `/queue/new` response also includes a `credentials` object with per-tenant NATS account credentials (MR-P0-5): ```json { "ok": true, "connection_url": "nats://nats.instanode.dev:4222", "subject_prefix": "tenant_a1b2c3d4....", "auth_mode": "isolated", "credentials": { "auth_mode": "isolated", "nats_jwt": "", "nats_nkey": "SUAA…", "creds_file": "-----BEGIN NATS USER JWT-----\n…", "key_id": "ABBA…" } } ``` Pass `(nats_jwt, nats_nkey)` to `nats.UserJWTAndSeed()` in the NATS Go client, or write `creds_file` to disk and pass the path to `nats.UserCredentials()`. When `auth_mode` is `"isolated"`, the tenant's JWT only permits pub/sub on the `subject_prefix.*` namespace and cross-tenant publish is denied at the server. > **Current production reality (read this).** Per-tenant account-JWT isolation > is wired end-to-end but is **not yet active in production** — prod currently > issues `auth_mode: "legacy_open"` for new queues (operator NKey generation is > pending). In `legacy_open` there is **no `credentials` block and no > server-side cross-tenant enforcement**: connect with just the > `connection_url`, and treat the queue as shared-namespace — scope your own > subjects under `subject_prefix.*` at the application layer. The `isolated` > shape above is what you'll receive once isolation is enabled. Resources > provisioned before the 2026-05-20 cutover are also `legacy_open`. ### Storage isolation mode (2026-05-20+) The `/storage/new` response also includes a `mode` field that names the isolation level the tenant landed on: | mode | Meaning | |---|---| | `broker` | **DO Spaces today — what every new tenant receives.** No long-lived credential is issued; the response omits `access_key_id`/`secret_access_key`. Use `POST /storage/:token/presign` for short-lived signed URLs (max 1h TTL). | | `shared-master-key` | Legacy DO Spaces rows only (pre-broker). Every tenant held the master key; isolation was by `prefix` convention. New tenants do NOT land here. | | `prefix-scoped` | Backend IAM enforces `s3:prefix` against `/*` (R2, S3, MinIO target). | | `prefix-scoped-temporary` | Same as prefix-scoped but credentials are STS — they expire. | The mode is decided at boot time by the `OBJECT_STORE_BACKEND` env var and the backend's `Capabilities()`. Agents should branch on `mode` if they need to behave differently — e.g. when `broker`, never try to write directly with `(access_key_id, secret_access_key)` since the response won't carry them. ### Broker-mode access: `POST /storage/{token}/presign` When the `/storage/new` response carries `mode: "broker"`, no long-lived credential was issued. Use this endpoint to mint a short-lived signed S3 URL (≤1h TTL) constrained to the resource's own `prefix/*`: ``` curl -X POST https://api.instanode.dev/storage/$TOKEN/presign \ -H "Content-Type: application/json" \ -d '{"operation":"PUT","key":"uploads/photo.jpg","expires_in":600}' # => {"ok":true,"url":"https://s3.instanode.dev/...?X-Amz-Signature=...","expires_at":"..."} ``` - `operation` — `"PUT"` (upload) or `"GET"` (download) - `key` — object key, will be prefixed with the resource's `/` internally; the path is scoped so a signed URL cannot escape the prefix even if leaked - `expires_in` — TTL in seconds, clamped to `[1, 3600]`; values ≤ 0 are rejected with `400 invalid_expires_in` The URL is signed by the platform master key but enforces the tenant's prefix at sign time, so leaked URLs cannot read or write other tenants' objects. Rate-limited per token. ## Operational endpoints - `GET /healthz` — shallow liveness probe. Returns 200 with `{ok, commit_id, build_time, version}` if the binary is up and can ping its primary platform DB. Use this to verify a deploy SHA matches what you pushed. - `GET /readyz` — deep readiness probe (added 2026-05-20). Multi-component upstream-reachability matrix returning per-check status + latency + last_checked timestamp. Per-check criticality decides 200 vs 503. See [Deploying an app](/docs#deploy) for the full envelope shape. - `POST /webhooks/brevo/:secret` — Brevo delivery webhook receiver (internal). Authenticated by URL token. Overwrites `forwarder_sent.classification` with the real outcome (`delivered`, `bounced_hard`, `bounced_soft`, `rejected`, `complaint`, `deferred`, `unsubscribed`, `error`) and stamps `delivered_at` on `delivered`. The truth surface for "did the user receive the email" — the worker's 201 from the Brevo API only means the relay accepted the POST; the ledger row's classification (set by this webhook) is the real outcome. ## Deploying an app `POST /deploy/new` takes a multipart form with a gzipped tar archive containing your Dockerfile + source. ``` curl -X POST https://api.instanode.dev/deploy/new \ -H "Authorization: Bearer " \ -F "tarball=@app.tar.gz" \ -F "name=expense-tracker" \ -F "port=8080" \ -F 'env_vars={"DATABASE_URL":"postgres://..."}' ``` `name` is **required** — it is the human-readable label for the deployment. Send it as a form field. It must be 1–64 characters and match `^[A-Za-z0-9][A-Za-z0-9 _-]*$` (start with a letter or digit; letters, digits, spaces, underscores and hyphens after). Omitting it returns `400 {"error":"name_required"}`; an invalid value returns `400 {"error":"invalid_name"}`. The build runs in-cluster on kaniko (~30–90s for typical Node/Python apps) and the app rolls out behind a public HTTPS URL on `*.deployment.instanode.dev` with a valid Let's Encrypt cert. `env_vars` is optional — pass a JSON object and every key/value lands in the app's environment on the first build. Saves you a follow-up PATCH+redeploy. For multi-service apps see **Stacks** below. ## Deleting a deployment (paid tiers — two-step, email-confirmed) Paid customers (Hobby, Hobby Plus, Pro, Growth, Team) can free a consumed deployment slot at any time. Because deletion is destructive — every byte of the running app + every env var — the agent CAN initiate but CANNOT finalise destruction. Only the human, by clicking the email link, completes the deletion. ### Step 1 — Initiate ``` curl -X DELETE https://api.instanode.dev/api/v1/deployments/ \ -H "Authorization: Bearer $INSTANODE_TOKEN" ``` Response (HTTP 202): ``` { "ok": true, "id": "", "deletion_status": "pending_confirmation", "confirmation_sent_to": "m***@instanode.dev", "confirmation_expires_at": "2026-05-14T10:30:00Z", "agent_action": "Tell the user to check their email at m***@instanode.dev. The deletion link expires in 15 minutes. To free the slot the user must click the link. The agent CANNOT confirm on the user's behalf — only the human can.", "cancellation_note": "Cancel by calling DELETE on the /confirm-deletion path, or let the 15-minute window expire." } ``` The agent surfaces `agent_action` to the user verbatim. The slot stays **consumed** until confirmation — a fresh `POST /deploy/new` still hits the per-tier `deployments_apps` ceiling. ### Step 2 — User clicks the email link The email link points at the API's `/auth/email/confirm-deletion?t=`, which 302s the user to the dashboard's `/app/confirm-deletion` page. The dashboard runs the authenticated POST: ``` curl -X POST 'https://api.instanode.dev/api/v1/deployments//confirm-deletion?token=' \ -H "Authorization: Bearer $INSTANODE_TOKEN" ``` Response (HTTP 200) → `deletion_status: "confirmed"`, slot is free. ### Cancel, expire, agent-override - **Cancel** (user changes their mind): `DELETE /api/v1/deployments/<id>/confirm-deletion`. Resource stays active. - **Expire** (15 minutes elapsed): the worker flips the row to `expired`. Re-running `DELETE` mints a fresh email. - **Agent override**: set `X-Skip-Email-Confirmation: yes` on the original `DELETE` → 200 immediate destruction. Use only when the agent has obtained explicit user consent on its own side. ### Anonymous tier Anonymous resources (24h TTL) have no email on file. `DELETE` returns 200 immediately — no two-step gate, since there is no inbox to mail. ### Stacks Same contract applies to `DELETE /api/v1/stacks/<slug>`. ## Health and readiness probes The platform exposes two distinct probes on every service (api, worker, provisioner): - **`GET /healthz`** — shallow liveness. Returns 200 with `{ok, commit_id, build_time, version}` if the binary is up and can ping its primary platform DB. Wired to Kubernetes `livenessProbe`. Use this to verify a deploy actually rolled out (`commit_id` should match the git SHA you pushed). - **`GET /readyz`** — deep readiness, added 2026-05-20. A multi-component matrix that walks every upstream the process depends on (platform_db, customer_db, redis-provision, provisioner_grpc, NATS, DO Spaces, Brevo, Razorpay, GeoIP). Per-check criticality decides the HTTP status: `platform_db` and `provisioner_grpc` are CRITICAL (a failed check returns 503 and pulls the pod from k8s rotation); everything else degrades to 200 with `overall=degraded` so a brevo outage degrades email but doesn't blackhole provisioning. Each check runs in parallel behind a 10-15s cache so the `readinessProbe` cycle doesn't self-DoS upstream rate limits. Response envelope (same shape across all three services): ```json { "ok": true, "overall": "ok", "commit_id": "abc1234", "checks": { "platform_db": {"status": "ok", "latency_ms": 4, "last_checked": "2026-05-20T..."}, "provisioner_grpc": {"status": "ok", "latency_ms": 12, "last_checked": "2026-05-20T..."}, "brevo": {"status": "degraded", "latency_ms": -1, "last_checked": "2026-05-20T...", "message": "brevo upstream timeout"} } } ``` `overall` is the worst non-degraded status the criticality matrix permits to be surfaced. New Relic alert `readyz_degraded` fires on `overall != "ok"` for 5 consecutive minutes per service. ## Stacks (multi-service deploy) `POST /stacks/new` takes an `instant.yaml` manifest plus one tarball per service. Services can reference each other with `service://<name>` env values — those resolve to cluster-internal `http://<name>:<port>` URLs at deploy time. The multipart form **requires** a `name` field — the human-readable label for the stack. It must be 1–64 characters and match `^[A-Za-z0-9][A-Za-z0-9 _-]*$` (start with a letter or digit; letters, digits, spaces, underscores and hyphens after). Omitting it returns `400 {"error":"name_required"}`; an invalid value returns `400 {"error":"invalid_name"}`. ``` curl -X POST https://api.instanode.dev/stacks/new \ -H "Authorization: Bearer <JWT>" \ -F "name=shop-stack" \ -F "manifest=@instant.yaml" \ -F "api=@api.tar.gz" \ -F "web=@web.tar.gz" ``` ``` services: api: build: ./api port: 3000 web: build: ./web port: 8080 expose: true env: API_URL: service://api ``` Only services with `expose: true` get a public URL — the rest are in-cluster only. The whole stack rolls out together; partial failure is reported per-service in `GET /stacks/{slug}`. ## Claim flow (anonymous → paid) Anonymous resources expire in 24 hours. To keep them, claim them. ``` RESP=$(curl -X POST https://api.instanode.dev/db/new \ -H "Content-Type: application/json" \ -d '{"name":"prod-db"}') JWT=$(echo $RESP | jq -r .upgrade_jwt) # Optional preview — shows what would attach, no side effects curl "https://api.instanode.dev/claim/preview?t=$JWT" # Trigger the claim — sends a magic link to your email curl -X POST https://api.instanode.dev/claim \ -d "{\"jwt\":\"$JWT\", \"email\":\"you@example.com\"}" ``` Click the magic link to set a session cookie. Every resource attached to your fingerprint transfers to your team atomically; the connection URLs don't change so any already-running code keeps working. Claimed resources move to your team's tier (hobby by default — $9/mo). There is no separate trial period on paid tiers — **the 24-hour anonymous slice is the trial**. ## Authentication Resource provisioning is anonymous. Everything else (deploy, vault, billing, team management) requires a session JWT. How to get one: 1. Provision any resource anonymously. The response includes a JWT in the `upgrade_jwt` field. 2. POST that JWT to /claim with an email. We send a magic link. 3. Click the link in the email; the page sets a session cookie. For unattended use (CI, agents), exchange the session cookie for a long-lived API key at `POST /api/v1/auth/api-keys`. Pass it as `Authorization: Bearer <key>` on every request. To verify a token works at any time, hit `GET /api/v1/whoami` — returns 200 with your team_id + plan_tier on success, 401 on failure. ## Tiers and limits | Tier | Postgres | Redis | MongoDB | TTL | Price | | ---------- | ----------- | --------- | ------------ | ---- | ----------- | | Anonymous | 10MB / 2c | 5MB | 5MB / 2c | 24h | free | | Hobby | 1GB / 8c | 50MB | 100MB / 5c | none | $9 / mo | | Pro | 10GB / 20c | 512MB | 5GB / 20c | none | $49 / mo | | Team | unlimited | unlimited | unlimited | none | $199 / mo | "c" = simultaneous connections. The full table is at `/pricing`. Hobby Plus and Growth exist in `plans.yaml` as upsell-only intermediate tiers reached via in-dashboard prompts when a Hobby user hits a quota wall. They are deliberately omitted from the public tier ladder to keep the customer-facing comparison simple. **Team tier status:** Team is live and self-serve at $199/mo (the API no longer returns `tier_unavailable` for `plan=team`). Note: self-serve checkout for ALL paid tiers (Hobby/Pro/Team) currently depends on the Razorpay recurring-billing rollout — until that operator step completes, `POST /api/v1/billing/checkout` may return a `502`/`503`; contact support@instanode.dev for assisted onboarding in the meantime. Limits are enforced at the Postgres user level (`CONNECTION LIMIT` on the role) and via per-bucket storage quotas. Exceeding a limit returns a 402 with an upgrade URL — your app keeps running, the next provision just fails. ## `POST /api/v1/billing/checkout` — concurrent-call dedup `POST /api/v1/billing/checkout` is server-side deduplicated per team. A second concurrent call for the same team — within a 60s window — gets a structured 409 instead of a second Razorpay subscription. This catches cross-tab clicks, mobile double-taps, retried form submits, and agents that retry the endpoint without coordination. Response envelope: ```json { "ok": false, "error": "checkout_in_flight", "message": "A checkout is already being created for this team. Wait ~60s and retry, or visit /dashboard to find the existing pending subscription.", "retry_after_seconds": 60, "agent_action": "Tell the user a checkout is already being created. They should wait ~60 seconds and refresh — the existing checkout link will appear in the dashboard.", "request_id": "..." } ``` The `retry_after_seconds` field tells callers how long to wait. The TTL also caps the worst case where the first caller crashes mid-flight — after 60s a retry is allowed automatically. The standard `Idempotency-Key` header (see `/docs/idempotency`) is honoured on this route too and provides a longer-window guarantee — pass it on every retry of a logical checkout attempt. If Redis is unavailable the dedup guard fails open (the call proceeds), with a `WARN billing.checkout.dedup_setnx_failed_open` log line. A Redis brownout must never block a paid upgrade — the idempotency middleware is the second layer of defence. ## Machine-readable API The full API surface is described in OpenAPI 3.1 at: ``` https://api.instanode.dev/openapi.json ``` It is the source of truth for paths, schemas, security schemes, and which endpoints accept anonymous traffic. Agents reading this spec alone can discover the claim flow (described under `securitySchemes.bearerAuth`), the `/api/v1/whoami` identity probe, and which fields like `upgrade_jwt` to pass forward. If you're an AI agent reading this, the recommended bootstrap is: 1. `GET /openapi.json` 2. Provision anonymous resources 3. `GET /api/v1/whoami` to confirm token validity once you have one