Skip to content

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

Terminal
$ 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 catalog

blobfish 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

Terminal
$ blobfish twin-runs create --twins salesforce --ttl 60 --wait

Hosted 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:

routing.env
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=0

Keep 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

MCP tools/list
$ 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

Terminal
$ 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

  1. Open BLOBFISH_TWIN_CONSOLE_ENDPOINT for endpoints, lease, the call ledger, runs, scenario capture, and the environment graph.
  2. Re-seed every service with blobfish twin-runs reset twe_<id>.
  3. Extend the serving lease with blobfish twin-runs extend twe_<id> --ttl 60; read the ledger with blobfish twin-runs logs twe_<id>.
  4. Terminate serving with blobfish twin-runs delete twe_<id>. The backing world remains protected retained data, but its endpoints stay revoked.
  5. Hosted runs: replace the example twe_* IDs with the returned tenv_* ID. The Kubernetes receipt includes the namespace, pinned images, workload identities, and observed health. blobfish twin-runs delete with --wait waits 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:

  1. Resolves your credential — BLOBFISH_API_KEY, else ~/.blobfish/credentials.json — and exits 2 with a blobfish login hint when neither exists.
  2. 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, --twins is required.
  3. Provisions with POST /api/v1/twin/environments (services, ttl_minutes — default 60 — and an optional --name) under an Idempotency-Key it keeps in a local pending file until the receipt is durable, so a retried timeout cannot allocate a second environment.
  4. Waits for ready (polling every 2 s, up to 600 s) and stops with the server’s error on failed, or if the run expires or enters teardown before it becomes ready.
  5. Writes routing.env and .blobfish-twin-run.json into --out-dir (default: the current directory).
  6. Composes a managed block for --env-file (default ./.env) — BLOBFISH_TWIN_ENV_ID plus every routing.env line between two marker comments — shows it, and asks Apply these changes? [Y/n]. --yes applies without asking; without a terminal and without --yes the file is left untouched.
  7. 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.
  8. 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.
  9. 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.
Terminal
$ blobfish twin wizard --twins github,slack --ttl 60 --yes
The managed block in .env
# >>> 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.

CommandWhat it does
blobfish twin wizard statusReads the environment named in .blobfish-session.json from the API and prints status, mounted services, endpoints, and expiry.
blobfish twin wizard resetRe-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 60Adds 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 teardownRequests 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 envRe-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.

Terminal
$ blobfish twin wizard env --yes

Restoring 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:

Terminal
$ 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 valueKindStatusOperationsEntities
Attioattiocaptured contractavailable34 (24 reads / 10 writes)26
Boxboxcaptured contractavailable273 (128 reads / 145 writes)191
Checkcheckdocs-transcribedavailable31 (14 reads / 17 writes)7
Datadogdatadogspec-groundedavailable133 (64 reads / 69 writes)26
Discorddiscordcaptured contractavailable128 (67 reads / 61 writes)71
Documensodocumensocaptured contractavailable17 (4 reads / 13 writes)13
Dropboxdropboxcaptured contractavailable12 (6 reads / 6 writes)9
GitHubgithubspec-groundedavailable1108 (581 reads / 527 writes)400
GitLabgitlabspec-groundedavailable1108 (486 reads / 622 writes)421
Gmailgmailspec-groundedavailable79 (30 reads / 49 writes)41
Google Calendargooglecalendarspec-groundedavailable38 (11 reads / 27 writes)11
Google Docsgoogledocsspec-groundedavailable4 (2 reads / 2 writes)3
Google Drivegoogledrivespec-groundedavailable64 (29 reads / 35 writes)40
Google Sheetsgooglesheetsspec-groundedavailable18 (6 reads / 12 writes)16
Google Workspacegoogleworkspacedocs-transcribedavailable34 (14 reads / 20 writes)7
HubSpothubspotspec-groundedavailable28 (13 reads / 15 writes)7
Jirajiracaptured contractavailable46 (25 reads / 21 writes)35
Linearlinearcaptured contractavailable25 (17 reads / 8 writes)12
LinkedInlinkedindocs-transcribedavailable29 (12 reads / 17 writes)6
Notionnotionspec-groundedavailable24 (12 reads / 12 writes)14
Outlook——roadmap——
QuickBooksquickbookscaptured contractavailable18 (7 reads / 11 writes)11
Resendresendcaptured contractavailable65 (28 reads / 37 writes)22
Salesforcesalesforcedomain twinavailable52 (20 reads / 32 writes)9
Slackslackspec-groundedavailable174 (57 reads / 117 writes)61
Stripestripespec-groundedavailable587 (262 reads / 325 writes)203
Trolleytrolleydocs-transcribedavailable51 (20 reads / 31 writes)10
Twilio——roadmap——
Unifiedunifieddocs-transcribedavailable28 (12 reads / 16 writes)6
Unstructuredunstructureddocs-transcribedavailable26 (12 reads / 14 writes)6
Waterfallwaterfalldomain twinavailable25 (11 reads / 14 writes)5

Next

Local testing · Custom scenarios · Models · Twin reference · Start a twin run