Guides
Twins quickstart
Create a Twin, inspect its runtime receipt, and connect your agent to its gateway. A configured dedicated runtime makes hosted environments (tenv_*) the default. Otherwise the deployment uses the website plane (twe_*). Select --plane cluster or --plane website explicitly when you need one of them.
To set this up in conversation, open Studio and ask: “Launch a hosted Salesforce Twin for 60 minutes.” The CLI below uses the same account and runtime APIs.
Prerequisites: Python 3.12+ and uv for the CLI, and an API key for your workspace. Creating runs also requires an active trial or subscription when subscription access is enabled; manage it from your account. If you want the shortest possible path on a single page, follow Start a twin run and come back here for the wizard, session management, and the twin table.
Install and sign in
$ uv tool install --with "blobfish-sdk @ https://blobfish.ai/sdk/blobfish_sdk-0.6.2-py3-none-any.whl" "blobfish-cli @ https://blobfish.ai/sdk/blobfish_cli-0.1.13-py3-none-any.whl"
$ blobfish login
$ blobfish twin catalogblobfish login (alias of blobfish twin login) verifies an existing API key or prompts for an email address and mints a key into ~/.blobfish/credentials.json. Creating that credential does not start a subscription; use a key belonging to your signed-in workspace for hosted runs. Account scope is derived from that credential; the client cannot select another account’s project. twin catalog lists every twin with its live mounted status and, when the cluster plane is configured, the admitted provider manifest merged in.
Provision a twin
$ blobfish twin-runs create --twins salesforce --ttl 60 --waitHosted creation is asynchronous. --wait reads the run until the backend reports ready, including observed workload health for the Kubernetes runtime. A failed or expired run exits with an error. To choose other twins, use blobfish twin-runs create --twins trolley --ttl 60 --wait or --twins github,slack. To use a shared website-plane world explicitly, add --plane website. Prefer the interactive path? blobfish twin wizard picks twins, provisions, and rewrites your .env with a backup (see What the wizard does and Local testing).
Load the receipt
The CLI writes routing.env and a private.blobfish-twin-run.json receipt. Inspect the returned run ID with blobfish twin-runs inspect and list its actual endpoints with blobfish twin-runs gateway. A hosted Salesforce run provides BLOBFISH_TWIN_SALESFORCE_MCP at /api/v1/twin/environments/tenv_<id>/mcps/salesforce/mcp. For a website-plane environment the routes look like this:
BLOBFISH_TWIN_ENDPOINT=https://blobfish.ai/api/v1/sandbox/worlds/sbx_<world>/mcp
BLOBFISH_TWIN_SALESFORCE_MCP=https://blobfish.ai/api/v1/sandbox/worlds/sbx_<world>/services/salesforce/mcp
BLOBFISH_TWIN_RUN_ENDPOINT=https://blobfish.ai/api/v1/twin/environments/twe_<id>
BLOBFISH_TWIN_CONSOLE_ENDPOINT=https://blobfish.ai/twin/twe_<id>
BLOBFISH_PRODUCTION_FALLBACK=0Keep the API key separate from this file. The receipt contains routes, never the credential. Every endpoint of an environment — per-service MCP, vendor-path REST, operations, reset, sessions, activity, CLI — is listed by GET /api/v1/twin/environments/twe_<id>/gateway (blobfish twin-runs gateway twe_<id>).
Connect an MCP client
$ set -a && source routing.env && set +a
$ curl -sS -X POST "$BLOBFISH_TWIN_SALESFORCE_MCP" \
-H "X-API-Key: $BLOBFISH_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'Use the per-service URL written by your create command. Hosted runs have isolated provider state; create a separate hosted run when you need an independent baseline. In a website-plane environment, session-less calls use the shared seeded world. To isolate a rollout, create a session (POST /api/v1/sandbox/worlds/sbx_<world>/sessions) and preserve the Mcp-Session-Id it returns on later calls: each session mutates its own copy-on-write database. Calls cannot fall through to production.
Run it with the model you ship on
$ blobfish twin-runs run twe_<id> --model claude-sonnet-5 --prompt "List the open opportunities and close the largest one"
$ blobfish twin-runs run twe_<id> --model grok-4 --api-key-env XAI_API_KEY --prompt "…"
$ blobfish twin-runs run twe_<id> --provider custom --base-url https://vllm.example.com/v1 --api-key-env MY_MODEL_KEY --model my-finetune --prompt "…"The commands above use the website-plane task runner. Claude, ChatGPT, Grok, DeepSeek, or any OpenAI-compatible endpoint of your own drive the twin’s real tools; every call lands in the ledger and the run record names the model and whose key served it. See Models.
Inspect and manage it
- Open
BLOBFISH_TWIN_CONSOLE_ENDPOINTfor endpoints, lease, the call ledger, runs, scenario capture, and the environment graph. - Re-seed every service with
blobfish twin-runs reset twe_<id>. - Extend the serving lease with
blobfish twin-runs extend twe_<id> --ttl 60; read the ledger withblobfish twin-runs logs twe_<id>. - Terminate serving with
blobfish twin-runs delete twe_<id>. The backing world remains protected retained data, but its endpoints stay revoked. - Hosted runs: replace the example
twe_*IDs with the returnedtenv_*ID. The Kubernetes receipt includes the namespace, pinned images, workload identities, and observed health.blobfish twin-runs deletewith--waitwaits for confirmed termination and namespace removal. A missing runtime or failed provisioning request reports an error; it does not silently switch to the website plane.
What the wizard does
blobfish twin wizard is the interactive form of step 2: it provisions an environment and wires the current project to it. Concretely, in order:
- Resolves your credential —
BLOBFISH_API_KEY, else~/.blobfish/credentials.json— and exits 2 with ablobfish loginhint when neither exists. - Picks the twins:
--twins github,slack, or, on a terminal, a numbered picker over the catalog entries that are mounted and available on this deployment. Without a terminal,--twinsis required. - Provisions with
POST /api/v1/twin/environments(services,ttl_minutes— default 60 — and an optional--name) under anIdempotency-Keyit keeps in a local pending file until the receipt is durable, so a retried timeout cannot allocate a second environment. - Waits for
ready(polling every 2 s, up to 600 s) and stops with the server’s error onfailed, or if the run expires or enters teardown before it becomes ready. - Writes
routing.envand.blobfish-twin-run.jsoninto--out-dir(default: the current directory). - Composes a managed block for
--env-file(default./.env) —BLOBFISH_TWIN_ENV_IDplus everyrouting.envline between two marker comments — shows it, and asks Apply these changes? [Y/n].--yesapplies without asking; without a terminal and without--yesthe file is left untouched. - Before the first write to an existing
.env, copies it to.env.blobfish-backup. That backup is created once and never overwritten — it stays your pre-wizard original. An existing managed block is replaced in place; otherwise the block is appended. - Saves
.blobfish-session.json(env_id, world_id, base, services, created_at, expires_at, env_file, env_backup, routing_env) so the session commands below know which environment they manage. - Prints the summary — console URL, one MCP URL per twin, expiry, the env file and its backup — and reminds you which files to add to
.gitignore.
$ blobfish twin wizard --twins github,slack --ttl 60 --yes# >>> blobfish twin wizard >>>
BLOBFISH_TWIN_ENV_ID=twe_<id>
BLOBFISH_TWIN_ENDPOINT=https://blobfish.ai/api/v1/sandbox/worlds/sbx_<world>/mcp
BLOBFISH_TWIN_RUN_ENDPOINT=https://blobfish.ai/api/v1/twin/environments/twe_<id>
BLOBFISH_TWIN_CONSOLE_ENDPOINT=https://blobfish.ai/twin/twe_<id>
BLOBFISH_PRODUCTION_FALLBACK=0
BLOBFISH_TWIN_GITHUB_MCP=https://blobfish.ai/api/v1/sandbox/worlds/sbx_<world>/services/github/mcp
BLOBFISH_TWIN_SLACK_MCP=https://blobfish.ai/api/v1/sandbox/worlds/sbx_<world>/services/slack/mcp
# <<< blobfish twin wizard <<<Session management
Every session command reads .blobfish-session.json from --out-dir and talks to the base the environment was provisioned on. None of them re-provisions.
| Command | What it does |
|---|---|
blobfish twin wizard status | Reads the environment named in .blobfish-session.json from the API and prints status, mounted services, endpoints, and expiry. |
blobfish twin wizard reset | Re-seeds the whole environment with one POST to …/environments/<id>/reset: shared state and every extant session fork return to the seeded baseline. The command reports the server's service/session counts and exits 1 if any part is incomplete. |
blobfish twin wizard extend --ttl 60 | Adds minutes to the lease (POST …/extend) and writes the new expires_at back into .blobfish-session.json. --ttl is the amount to add; default 60. |
blobfish twin wizard teardown | Requests teardown, waits for the backend to confirm termination, removes .blobfish-session.json, and prints where your .env backup is. It never edits .env. |
blobfish twin wizard env | Re-fetches the environment and rewrites routing.env and the managed .env block from the current record — no provisioning. --yes applies without prompting. |
Re-run just the .env step
If the managed block was removed by hand, the env file moved, or you simply want routing.env regenerated from the current environment record, blobfish twin wizard env --yes rewrites both without touching the environment itself. It uses the env file recorded in the session (or --env-file), backs it up first if no backup exists yet, and updates the session file.
$ blobfish twin wizard env --yesRestoring your original .env
The wizard never deletes anything from your .env; it only adds or replaces its own marked block. To go back to exactly what you had before the first wizard run, copy the backup over it — teardown prints this same command with the paths it recorded:
$ cp .env.blobfish-backup .env.env.blobfish-backup exists only if a .env existed when the wizard first wrote to it. If there was none, the file is entirely the wizard’s: delete it, or remove the block between # >>> blobfish twin wizard >>> and # <<< blobfish twin wizard <<<.
Available twins
Projected from each twin’s own resolved spec, the same way blobfish twin catalog and the Twin reference read it. The --twins value is the service key, which differs from the catalog slug for the Google twins (googlecalendar, not google-calendar); an unknown key answers 422 twin_service_unavailable with the mountable list. Operations are the spec’s declared count; a one- or two-twin environment mounts up to 120 of them per twin.
| Twin | --twins value | Kind | Status | Operations | Entities |
|---|---|---|---|---|---|
| Attio | attio | captured contract | available | 34 (24 reads / 10 writes) | 26 |
| Box | box | captured contract | available | 273 (128 reads / 145 writes) | 191 |
| Check | check | docs-transcribed | available | 31 (14 reads / 17 writes) | 7 |
| Datadog | datadog | spec-grounded | available | 133 (64 reads / 69 writes) | 26 |
| Discord | discord | captured contract | available | 128 (67 reads / 61 writes) | 71 |
| Documenso | documenso | captured contract | available | 17 (4 reads / 13 writes) | 13 |
| Dropbox | dropbox | captured contract | available | 12 (6 reads / 6 writes) | 9 |
| GitHub | github | spec-grounded | available | 1108 (581 reads / 527 writes) | 400 |
| GitLab | gitlab | spec-grounded | available | 1108 (486 reads / 622 writes) | 421 |
| Gmail | gmail | spec-grounded | available | 79 (30 reads / 49 writes) | 41 |
| Google Calendar | googlecalendar | spec-grounded | available | 38 (11 reads / 27 writes) | 11 |
| Google Docs | googledocs | spec-grounded | available | 4 (2 reads / 2 writes) | 3 |
| Google Drive | googledrive | spec-grounded | available | 64 (29 reads / 35 writes) | 40 |
| Google Sheets | googlesheets | spec-grounded | available | 18 (6 reads / 12 writes) | 16 |
| Google Workspace | googleworkspace | docs-transcribed | available | 34 (14 reads / 20 writes) | 7 |
| HubSpot | hubspot | spec-grounded | available | 28 (13 reads / 15 writes) | 7 |
| Jira | jira | captured contract | available | 46 (25 reads / 21 writes) | 35 |
| Linear | linear | captured contract | available | 25 (17 reads / 8 writes) | 12 |
linkedin | docs-transcribed | available | 29 (12 reads / 17 writes) | 6 | |
| Notion | notion | spec-grounded | available | 24 (12 reads / 12 writes) | 14 |
| Outlook | — | — | roadmap | — | — |
| QuickBooks | quickbooks | captured contract | available | 18 (7 reads / 11 writes) | 11 |
| Resend | resend | captured contract | available | 65 (28 reads / 37 writes) | 22 |
| Salesforce | salesforce | domain twin | available | 52 (20 reads / 32 writes) | 9 |
| Slack | slack | spec-grounded | available | 174 (57 reads / 117 writes) | 61 |
| Stripe | stripe | spec-grounded | available | 587 (262 reads / 325 writes) | 203 |
| Trolley | trolley | docs-transcribed | available | 51 (20 reads / 31 writes) | 10 |
| Twilio | — | — | roadmap | — | — |
| Unified | unified | docs-transcribed | available | 28 (12 reads / 16 writes) | 6 |
| Unstructured | unstructured | docs-transcribed | available | 26 (12 reads / 14 writes) | 6 |
| Waterfall | waterfall | domain twin | available | 25 (11 reads / 14 writes) | 5 |
Next
Local testing · Custom scenarios · Models · Twin reference · Start a twin run