# FlyMyAI - connected assistant operating guide Platform version: Headless Cloud 1.10.10 (2026-10-07). This guide is the current snapshot. History: https://flymy.ai/changelog.md and https://flymy.ai/changelog.json. Call `whats_new` with `since` set to the last version seen when connecting or when asked what is new. > `https://flymy.ai/skill.md` and `https://flymy.ai/AGENTS.md` serve the same bytes. > Candidate guide: Agents MCP `0.7.0-rc.29`, Python SDK `1.2.0rc5`. > Check installed packages and live MCP schemas before relying on this contract. ## Build a project in about ten calls A project is usually one complete agent: find its tools, create it, run it, freeze the accepted run, then schedule, share, or embed it. 1. `whoami` - confirm FlyMyAI is connected and which account it is. 2. `search_tools` with a plain-English intent per service, then `get_tool_schemas` for exact fields. 3. If a service is not `configured`, `add_tool`; the user finishes the hosted link; confirm with `list_configured_tools`. 4. `create_agent` once: goal, numeric connection IDs in `available_tools`, optional `model` from `list_agent_models`, `input_schema` and `output_schema`. 5. `run_agent` with a new `operation_key`; poll `get_run` until `poll_complete=true`; `read_run_result` if the preview is truncated. 6. Refine the same agent (`update_agent` or `append_message`) until the user accepts one completed run. 7. `freeze_agent` with that execution ID; poll `get_compilation` until `status=compiled`. 8. `run_frozen` with a new `operation_key` and poll `get_run` before calling it production-ready. 9. Ship: a schedule (`update_compilation`), a public template (`set_agent_public`), a subagent of a lead, or a product deployment. 10. Media: `recommend_model`, `get_pricing`, then `run_model`. | Section in this file | Docs | | --- | --- | | Start here | https://docs.flymy.ai/agents/guides/ai-assistants | | Tools and connections | https://docs.flymy.ai/agents/concepts/tools | | Multiple accounts and resource sets | https://docs.flymy.ai/agents/guides/mcp-resource-sets | | Models | https://docs.flymy.ai/api/models-endpoints | | Agents, every MCP tool | https://docs.flymy.ai/agents/guides/agent-gateway-reference | | Projects, artifacts, sites | https://docs.flymy.ai/agents/guides/projects | | Embedded and resale | https://docs.flymy.ai/agents/guides/embedded-resale | | Browser Use | https://docs.flymy.ai/mcp/browser-use | | Your own model on GPU | https://docs.flymy.ai/cli/intro | | Release maintainers only | https://docs.flymy.ai/agents/guides/release-gates | ## Start here - verify FlyMyAI or recover FlyMyAI gives this assistant hundreds of connectors and actions, the model catalog, and serverless agents. It may already appear as the `flymyai` MCP server. Make one bounded read-only call such as `whoami`, `tools/list`, `search_tools`, or a `list_*` tool before claiming it is connected. If the server or tools are absent, do not claim success and do not guess tool names. Ask the user to connect the exact intended environment. GUI clients can use OAuth sign-in. Configuration-driven clients use the exact `FLYMYAI_MCP_URL` and an `X-API-Key` supplied from their secret manager, never pasted into chat. If MCP remains unavailable, use REST only after the caller supplies an authenticated `FLYMYAI_AGENTS_API_ROOT`; otherwise report that preflight is blocked. A release-candidate run must use an explicit candidate release contract, MCP, skill, and Agents API roots and must never fall back to production. ```bash export FLYMYAI_MCP_URL=https://mcp-agents.flymy.ai/mcp export FLYMYAI_AGENTS_API_ROOT=https://backend.flymy.ai/api/v1/agents claude mcp add --transport http flymyai "$FLYMYAI_MCP_URL" \ --header "X-API-Key: $FLYMYAI_API_KEY" ``` Those are the released production values. If FlyMyAI is already connected, do not reinstall it. Before a mutation, read its live schema - for example the live `update_agent` schema from MCP `tools/list` - instead of guessing fields. Golden rule: never assume a capability is missing - assume it exists here and verify with search_tools / list_* BEFORE declining or asking the user where to find a service or model. Discovery is not evidence of success. ## Tools and connections 1. Call `search_tools` with a plain-English intent; read `tool`, `action`, `runtime_name`, and `configured`. Never download the full catalog (over 1.7 MiB) per intent. 2. Call `get_tool_schemas` with the `runtime_name` when search did not inline the request schema. Never call a create, update, send, append, batch-write, or delete action with empty or guessed arguments to learn its schema. If lookup returns `not_found`, use the agent runtime or stop - do not probe. 3. If configured, call `execute_tool` with exactly `tool`, `action`, `arguments`, and a caller-owned stable `operation_key`. To select a non-default instance, pass its exact configured-tool public UUID as `connection_id`; omission is supported only while one eligible connection is unambiguous. Run OAuth/Composio actions inside an agent. 4. If not configured, call `add_tool` with the tool slug. It returns the exact connection record or guidance with a hosted `https://app.flymy.ai/mcp-configs#?connection_id=` link. After the user finishes, call `list_configured_tools`, match the exact `public_id` and `alias`, and inspect `is_configured`, `connection_status`, `connection_status_reason`, `connection_status_valid_until`, and `connect_url`. Do not invent a `setup_url` response field. 5. To revoke exactly one connection, call `delete_tool` with its numeric `id` (REST: `DELETE /api/v1/agents/tools/{id}/`); sibling connections of the same toolkit keep working, and the revoked row fails before any provider call. ```text search_tools({"query":"telegram list dialogs"}) get_tool_schemas({"runtime_names":["custom--telegram--telegram_list_dialogs"]}) execute_tool({"tool":"telegram","action":"telegram_list_dialogs", "arguments":{"query":"FlyMyAI"},"operation_key":"telegram-dialogs-"}) ``` The parameter is literally `arguments`; `params` or `input` returns HTTP 400. `outcome=rejected` means FlyMyAI or the provider refused before any effect (wrong arguments, missing setup, provider refusal): fix the call and send it with a new `operation_key`. `outcome=unknown` means it may have taken effect: reconcile, never repeat automatically. Without MCP tool calls, POST `{"tool":"system-utils","action":"search_tools","arguments":{"query":"...","limit":20}}` and then `get_tool_schemas` (at most 10 runtime names) to `$FLYMYAI_AGENTS_API_ROOT/custom-tools/call/` with `X-API-KEY`; read `result.schemas[runtime_name].request_schema` and call the returned `module` as `tool`. Details: https://docs.flymy.ai/agents/concepts/tools ### Personal default - one account, no MCP resource-set setup Set `mcp_access_mode` to `legacy` for this direct personal projection; switch it explicitly to `scoped` only when granting named resource sets. 1. Start in the user's implicit personal space and call `search_tools`. 2. If the toolkit is not connected, send the hosted setup link or the row's `connect_url`. A programmatic flow may call `add_tool` without `alias`, which addresses the idempotent `default` connection. 3. Call `list_configured_tools` with exact `mcp_tool` and `alias:"default"` and keep the numeric `id`. Require `is_configured:true`: `connected` is ready, `setup_required` or `reconnect_required` needs the hosted link, `verification_pending` needs a bounded live read, and `temporarily_unavailable` is reported, not bypassed. 4. Pass that ID in `available_tools` on `create_agent` or `update_agent`. Do not require the user to create or name resource sets, groups, slots, grants, principals, revisions, or mappings for this first successful flow. The default connection is a safe projection of the same exact persisted identity and authority model used by the advanced path, and can join a named set later without rebuilding the agent or reconnecting the account. ### Grow into multiple accounts and MCP resource sets Aliases are labels; authorization, dispatch, and freeze use stable public IDs. Add each account with `add_tool` and a unique `alias` (ASCII letters, digits, `_`, `-`), create one set with `create_mcp_resource_set` and a caller-owned `operation_key`, write the full membership with `replace_mcp_resource_set_members` at the current revision (reload after 409), and grant it through `mcp_resource_set_ids` with `mcp_access_mode:"scoped"`: ```text support = add_tool({"mcp_tool":"gmail","alias":"support"}) rs = create_mcp_resource_set({"name":"Inbox operations", "management_mode":"flymyai","operation_key":"inbox-set-"}) rs = replace_mcp_resource_set_members({"resource_set_id":rs.public_id, "expected_revision":rs.revision,"members":[{"resource_type":"user_mcp_tool", "resource_id":support.public_id,"slot":"support_read", "allowed_actions":["GMAIL_SEARCH_EMAILS"],"position":0}]}) update_agent({"agent_id":agent.uuid,"available_tools":[], "mcp_resource_set_ids":[rs.public_id],"mcp_access_mode":"scoped"}) ``` An omitted attachment field is unchanged; an explicit empty array clears that relation. Include the old `default` connection in the set if the agent must keep it, then verify with `get_agent`; otherwise the direct connection and set grants form a union. - One owner may retain at most 25 connection rows for one toolkit, including inactive ones; `is_active:false` does not free a slot, deleting a row does. - Owner sets use `management_mode:"flymyai"` and omit `principal_id`; a customer mapping uses `management_mode:"customer"` with the exact `principal_id`. Never send deprecated `external_principal_id`. - Member identity is `(resource_type, resource_id, slot)`: the same exact resource may appear in several slots, and each slot keeps its own `allowed_actions` ceiling. Omitting or sending `allowed_actions:[]` means unrestricted, not deny all; for least authority send exact read actions. - One scoped agent execution admits at most 100 MCP resource sets, 500 effective connector bindings, 100 logical slots, 5,000 allowed-action entries, and 1 MiB of UTF-8 allowed-action text. An oversized authority graph fails closed before provider dispatch. - `create_agent_group` shares a set across agents. Groups are flat: a child or subagent does not inherit a parent's connector authority. - When several granted connections can run one action, its runtime schema requires `_flymyai_connection`: pass one allowed `public_id` from it, never an alias or row order. Direct `execute_tool` uses the exact `connection_id`. - Freeze records set membership, connections, slots, ceilings, and revisions. New accounts mean the same agent UUID, a new frozen version, and the same stable deployment ID; older versions and customer slot mappings do not change in place. If resource-scope mutations are not enabled, keep the `default` behavior and report it; never pick a first row silently. The list tools `list_configured_tools`, `list_mcp_resource_sets`, `list_mcp_resource_set_members`, and `list_agent_groups` return `{next_cursor, previous_cursor, results}`. Use `page_size` from 1-100, treat `cursor` as an opaque, nonblank printable string of at most 1024 Unicode code points, and pass the opaque `next_cursor` back unchanged until it is null; `list_agents` pages the same way. The configured-tool list accepts only exact `mcp_tool` and `alias` filters; rows are compact, so filter by `mcp_tool` or pass `view=full` for setup fields. `list_mcp_resource_sets` rows are summaries with `member_count` and no nested members; use `get_mcp_resource_set` for one bounded full set or `list_mcp_resource_set_members` for a large member collection. Both `replace_mcp_resource_set_members` and `update_mcp_resource_set` require the current `expected_revision`. Details: https://docs.flymy.ai/agents/guides/mcp-resource-sets ### Shared connections and your own MCP servers Personal MCP sharing gives the recipient every shared action of the connection, reads and writes, on the owner's account, from any sign-in: an API key or the OAuth sign-in of Claude, ChatGPT or Grok. `list_shareable_mcp_connections` says what can be shared and with what access. `invite_mcp_user` shares one by email, or with a teammate by `member_id` from `list_mcp_share_people`, after the user confirms the connection, recipient, and period (1, 7, 14 or 30 days, or `access_days: 0` until revoked); its key is 8-128 printable non-space ASCII characters. `list_mcp_shares` and `list_mcp_invitations` show both directions; `accept_mcp_invitation` only after the user agrees to pay for their own calls; `revoke_mcp_access` stops a share; `list_mcp_share_activity` lists its calls. `list_configured_tools` lists accepted shares next to the user's own connections under `shared_with_me`: check it before saying a service is not connected; call one with `list_shared_mcp_tools` and `call_shared_mcp` and a stable `operation_key`. The recipient pays; the owner's credentials never leave FlyMyAI. Agents use the user's own connections first and see shared ones with who shared each: without an own connection of that toolkit they use the shared one, otherwise only when the user asks for it. A write changes data in the owner's account; tool annotations say which only read. Details: https://docs.flymy.ai/agents/guides/mcp-personal-sharing For an MCP server not in search, call `add_mcp_server` (OAuth: `auth_type:"oauth"`, then `authorize_mcp_server`, give the user its `authorize_url`), then `connect_mcp_server`; use `discovered_tools` only at `status:"connected"`. Call it with `call_mcp_server` (`server_id`, `action`, exact `arguments`, stable `operation_key`, sent as `Idempotency-Key`). Details: https://docs.flymy.ai/agents/guides/mcp-servers ## Models - discover, price, run ```text recommend_model({"description":"cheap flat icon image", "include_schema":true,"top_n":1}) run_model({"endpoint_id":"flymyai/nano-banana", "input":{"prompt":"A blue circle, flat icon"}}) ``` Use the returned endpoint, schema bounds and price; a guessed paid call is not discovery. `get_pricing` quotes a listed model before a paid run. Over REST, `GET https://backend.flymy.ai/api/v1/demo/catalog/` (no key) gives each public model a `price` (`run_price`, or usage-based `rates`, `tokens` or `run_time`). `run_model` gives each generated file a `url` valid until `url_expires_at` (15 minutes max). Chat models also carry `openai.base_url` (`https://api.flymy.ai/api/v1//openai/v1`): the OpenAI SDK works with it and the FlyMyAI key as Bearer token for `messages` with text and `image_url`, `stream` and `reasoning_effort`; `tools`, `tool_choice` and `response_format` are rejected. Guide: https://docs.flymy.ai/guides/llm-openai-compat Grok 4.7 (`flymyai/grok-4_7`) also applies `max_tokens`, `temperature`, `top_p`, `xhigh` effort and sync-only `private_mode: true` (no text kept); no `/predict/stream/`. Guide: https://docs.flymy.ai/guides/grok-4-7 Wan 3.0 (`flymyai/wan-3_0-t2v`, `-i2v`, `-ref2v`): 2-30 s video with sound, paid per second, 720P by default. Guide: https://docs.flymy.ai/guides/wan-3-0 Model REST inputs are model-specific `multipart/form-data`, not JSON; read `https://api.flymy.ai/api/v1/flymyai//openapi.json` first. ```bash curl -fsS --no-buffer --max-time 60 -H "X-API-KEY: $FLYMYAI_API_KEY" \ -F 'prompt=Reply exactly FLYMYAI_OK' \ https://api.flymy.ai/api/v1/flymyai/google-gemini-31-flash-lite-preview/predict/stream/ ``` Concatenate the `output_data.output` chunks; the last event has `stream_details` token counts. Check body-level status even on HTTP 200. The Python SDK is `pip install 'flymyai==1.2.0rc5'`; images come back base64: prefer URL or async outputs for large media. Usage: `GET https://api.flymy.ai/api/v2/usage` over a bounded date range (lags 20+ s; `total_price` is account usage). Details: https://docs.flymy.ai/api/models-endpoints and https://docs.flymy.ai/clients/python TypeSafe Jev 1.13 answers typed questions (routing, triage, guardrails): Choice, Noul (yes probability) or Score (ordered levels); text only, 32K context. Use `typesafe_jev.decide` in agents or `make_typed_decision` on either MCP server; answers carry `charge_usd`. Guide: https://docs.flymy.ai/guides/typesafe-jev ## Agents - create, run, freeze, schedule Author with the Agents MCP; call published results through REST or the SDK. Define one agent's goal, tools, inputs and output; `create_agent` once, then refine until the user accepts a completed run. Inputs, customers and connections reuse it unless the user asks for a multi-agent system. The agent's LLM is `model`, an id from `list_agent_models` (each with speed, power and cost bands and effort options), with optional `effort`, on `create_agent` or `update_agent`; omit it for the platform default and pick a cost-1 model for helpers and subagents. ```text agent = create_agent({"name":"Health check","mcp_access_mode":"legacy", "user_prompt":"Return a JSON object with status set to ok."}) run = run_agent({"agent_id":agent.uuid,"variables":{}, "operation_key":"health-run-"}) page = get_run({"execution_id":run.id}) # repeat with since=page.next_since frozen = freeze_agent({"execution_id":run.id}) get_compilation({"compilation_id":frozen.id}) # until compiled or failed test = run_frozen({"compilation_id":frozen.id, "operation_key":"health-frozen-"}) ``` `run_agent` and `run_frozen` return a short receipt (`id`, `status`, `run_seq`, `subagent_limits`); poll `get_run` with `since` while `poll_complete=false`. The final page has `result` and `error` previews of 4 KiB with `size_bytes`, `sha256`, and a `ref`. For the whole value call `read_run_result({"execution_id":run.id,"ref":page.result.ref})`, passing `offset` equal to `next_offset` until `complete=true` (64 KiB per call), and check the joined bytes against `sha256`. After a follow-up message, take a fresh `ref` from `get_run`. Variables never need another agent: define `input_schema` and matching `{{ placeholders }}` in `user_prompt` and pass real `variables`; freeze takes the execution ID, optional `guidance` (what the compiler must keep as is, up to 20,000 characters), and later runs pass fresh variables. The freeze artifact is `compilation.id` plus `instruction_md`, not a source file. After a frozen test run its status can be `running`, `completed`, or `failed`; `completed` is publish-ready, not a reason to freeze again. Hand back the IDs, `instruction_md`, schemas, a frozen test run and integration code. Scheduling: before freeze, `schedule_agent({"execution_id":...,"cron_schedule":"0 9 * * 1-5","timezone":"UTC","schedule_variables":{}})` freezes and schedules once. Already frozen: `update_compilation` with the same fields on that compilation ID (REST: PATCH `/compilations/{id}/`); do not call `schedule_agent` again. `cron_schedule:""` unschedules. `schedule_agent` has no idempotency key: after a timeout, reconcile compilations for that execution before retrying, or you may create a second active cron. After 3 failed scheduled runs in a row the schedule pauses and the owner is emailed: `get_compilation` shows `schedule_paused` and `schedule_paused_reason`. Fix the cause, then resume with `update_compilation` and the cron. After freeze, the owner calls `POST /api/v1/agents/compilations/{compilation_id}/run-instruction/` with a persisted `Idempotency-Key` and polls `/executions/{id}/status/?since=`. Product customers use a deployment (next sections; go there directly when the request names one). The SDK `AgentClient` creates, runs, and freezes agents and runs compilations, but does not schedule. Details: https://docs.flymy.ai/agents/guides/serverless-agents ## Subagents - a lead runs your other agents Any ordinary run can start subagents. `subagent_limits` on `run_agent` or `run_frozen` sets the lead's allowance: `cap_usd` (subagents and their tools; 0 turns them off), `max_children` (1-6), `max_parallel` (1-3) and `agents`, up to 10 of your agent ids the lead may start. The chat Subagents control sets the same values. Inside the run the lead has these tools: - `list_subagents` - the allowed agents with their model and inputs. - `delegate_agent(agent=..., brief, variables)` - runs that agent with its own model, prompt, tools and MCP servers; `variables` fill its inputs. - `delegate_agent(model=..., brief)` without `agent` - a copy of the lead with its tools on another model from `list_agent_models`. - `wait_subagents`, `subagent_status(child_id)` (a large result in full) and `cancel_subagents`; the lead joins a batch of delegations automatically. - `describe_subagent_api`, `freeze_subagent` (from that agent's last completed subagent run) and `schedule_subagent` manage the allowed agents. Each subagent stops when it spends its share of `cap_usd`. A subagent cannot start subagents, and connections other people shared with you do not reach it. `get_team_run` shows each subagent's agent, model and spend. A lead whose frozen instruction uses `delegate_agent` pins the frozen version of each allowed agent when it is frozen, so freeze those agents first. Its scheduled runs start the pinned versions, which receive only their `variables`. The older `delegate` tool still starts a bounded copy of the lead with web search and shared files. A lead and the agents it starts are a fleet, listed as a project (`fleet:`). ## Projects - one config with pages, agents, storage and budgets A project is its `flymy.yaml`: pages, agents, storage and budgets. `projects_plan` shows price; `projects_create` applies the approved `plan_token`. Clone your app with `template=app:/` in both calls, or **Clone** in its workspace: new private resources and budget, without stored data, chats or personal connections. Others require a gallery template. `apps_plan` / `apps_apply` change it; poll `apps_status`. `projects_list`, `projects_get`, `projects_errors` show apps, pages, fleets and artifacts. `projects_stop` / `projects_start` pause/resume. Storage tools: `apps_storage_list`, `apps_storage_read`, `apps_storage_write`. https://app.flymy.ai/projects: picker, agents, graph, resizable master chat and histories. Projects menu opens Home and other sections. Claude/Codex keeps its host chat; give the cloud master a brief, resource limits and reporting cadence. Compaction saves private archives with `read_context_checkpoint` pointers. Find this agent's earlier archives via task `search_memory` in `context_checkpoints`; isolated runs stay isolated. Keep decisions, open work and when-to-read file notes. Old plans grant no new approval. Artifacts: `create_artifact` (private; no keys in files), `publish_artifact_version`, `share_artifact` (link/public, optional sources), `clone_artifact`. `add_artifact_member` invites an email/username to view/edit; access begins on acceptance: `list_artifact_invitations`, `accept_artifact_invitation`, `decline_artifact_invitation`. Owners see only the identity they entered. Sites: `publish_site`, `share_site`, `invite_to_site`, `get_site_usage`; declared model/agent calls use the owner's sponsor pool or consenting visitors' wallets, within daily caps. Details: https://docs.flymy.ai/agents/guides/projects and https://docs.flymy.ai/agents/guides/artifacts ## Templates - share, fork, and media templates Only when the user asks, `set_agent_public` makes one of their agents a public template; `copy_agent` forks an agent into the user's account to change, freeze and ship. A lead comes with the agents it runs as subagents, all or none. The gallery at https://flymy.ai/media holds live media templates: run one as is, or clone it with `copy_agent`, adapt it and freeze your own endpoint. Details: https://docs.flymy.ai/agents/guides/media-templates ## Embedded and resale - one builder key, no end-user keys One builder key on the builder backend serves every product user, who connects their own services. Never ask an end user to create a FlyMyAI account or paste a key. - Keep `FLYMYAI_API_KEY` only in a server secret manager, never in clients, URLs, logs, or chat. - Author and owner-test through MCP. Deployment publish and customer connect-session are Agents REST; do not invent `client.deployments` calls unless the installed SDK exposes them. MCP `whoami` and `GET /api/v1/agents/me/` with the builder key must return the same `user_id`; customer identity is never that owner session's `user_id`. - Publish the frozen version as one stable deployment (draft, `access`, preflight, publish) and upgrade or roll back by staging another immutable version on the same deployment ID. If preflight rejects a toolkit, keep the worker whole and report it; do not split it or bypass preflight. - `external_user_id` is the builder's stable, opaque, non-secret ID (at most 255 characters, not starting with `flymyai-owner-`). Normal product IDs come from authenticated server sessions, never from the client, an email, or a secret. `external_user_id` selects the external principal only. - The deployment `access` GET is read-only. The `connect-session` POST is the first mutating bootstrap for a new user: send only its `redirect_url` (single-use, 15 minutes) to that user, then poll `access` with backoff. It has no idempotency key, so reconcile a lost response through `access`. - FlyMyAI bills the deployment owner; there is no per-user rollup, so ledger `external_user_id`, deployment, execution ID and idempotency key yourself and read `/executions/{id}/prices/`. Mapping modes, chosen on every run: - FlyMyAI-managed binding - omit both `resource_set_id` and `connections`. - Customer-managed named mapping - store a principal resource-set `public_id` and `revision`, and send both `resource_set_id` and `resource_set_revision` on every run; members are `resource_type:"integration_connection"` IDs. - One-off mapping - `connections` keyed by frozen slot. `resource_set_id` and `connections` are mutually exclusive. Omitted slots currently continue through saved bindings, so send every required slot when the request must own the whole mapping. Owner connection IDs are never valid, and a customer principal never falls back to the owner's authoring connection. ```bash curl -fsS --max-time 30 -X POST -H "X-API-KEY: $FLYMYAI_API_KEY" \ -H "Idempotency-Key: $PERSISTED_DEPLOYMENT_RUN_KEY" \ -H 'Content-Type: application/json' \ --data '{"external_user_id":"customer_42","variables":{}}' \ "$FLYMYAI_AGENTS_API_ROOT/deployments/$DEPLOYMENT_ID/run/" ``` A HTTP 400 under `connections` means a missing or invalid slot. A customer-bound MCP process (`FLYMYAI_MCP_MODE=customer`) has one immutable deployment/customer binding per gateway process, set by trusted server configuration; the deployment, `external_user_id`, and mapping are process settings. Those authority values are never model-call arguments. Its client authenticates with a customer edge token, not the owner key, and sees only `run_bound_deployment` and `get_bound_deployment_run`. Two customers on one deployment get different principals and executions while keeping the same agent, frozen version, deployment, and billed owner. Scripts: https://docs.flymy.ai/agents/guides/embedded-resale ## Browser Use - real browser tasks `run_browser_task` drives a remote browser; `wait_for_browser_task` is a pure read; `send_task` continues and `stop_browser_task` ends a session. New sessions use `gpt-6-luna` by default; pass `model` to pick another. - Use the same existing public `execution_id` and exact connection for create, poll, files, follow-up and stop. - Never put passwords in prompts. **Create saved browser** (or `client.tools.create_browser_profile`) binds a profile to the connection; the user signs in once in the live view. On an unknown result or 409, inspect with `get_browser_profile` and `reconcile_browser_profile`, never create again. Use a second connection for a second account, and end with `stop_browser_task(strategy="session")`. - `live_url`, `live_url_clean`, and `share_url` are full-control credentials: only for the requesting user, never published or logged. - Media becomes durable only through `get_browser_recording(persist=true)`, `recover_browser_artifact`, or `download_browser_file` (256 MiB budget). In chat, show the signed `ALLOW_BROWSER_USE_*` lines, stop, and repeat with the token only after the user sends them. Never manufacture that acknowledgement. Tokens are one-time, short-lived, execution-bound, connection-bound, and request-bound. - A status or recording is not proof a file was downloaded or that a social site is supported. Details: https://docs.flymy.ai/mcp/browser-use ## Your own model on GPU - FlyMyAI CLI Deploy your Python model as an auto-scaling GPU endpoint, billed for its compute, with the FlyMyAI CLI (`fma`): ```bash pip install git+https://github.com/flymyai/fma-custom-models.git fma init my_model # model.py with initialize() and predict() fma login # the user signs in; never ask for the password in chat fma deploy # then fma logs, fma update, fma delete ``` Details: https://docs.flymy.ai/cli/intro ## Auth, errors, and resource discipline Never print, echo, or read back credentials or the environment (`env`, `printenv`, `echo $KEY`); reference secrets only as variables. REST uses `X-API-KEY`; models are at `https://api.flymy.ai`, keys at `https://app.flymy.ai/profile`, docs at `https://docs.flymy.ai`. - Every run submission requires an explicit caller-owned retry identity. MCP `run_agent` and `run_frozen` require a nonblank printable ASCII `operation_key` of at most 255 characters with no leading or trailing spaces. REST task runs (`/tasks/{id}/run-loop/`), compilation runs (`/compilations/{id}/run-instruction/`), and deployment runs (`/deployments/{id}/run/`) send the same value as `Idempotency-Key`. Neither gateway nor backend generates a fallback. Reserve it with the request before dispatch, reuse it only for the identical request, and use a new key per logical run. - MCP `create_mcp_resource_set` and `create_agent_group` are durable creates and require their own caller-owned `operation_key`. Their REST collection POSTs require the same value in `Idempotency-Key`. The same key and body replay the original response; a changed body returns 409. After a lost response, retry that body with that key, never a new key. - A REST replay returns the same execution for 2 days; later reuse can create a new one, and a concurrent replay can return 409. - `create_agent`, `freeze_agent`, deployment creation, and `connect-session` have no replay key: record an audit label and the request before dispatch, persist returned IDs, reconcile a lost response by bounded reads, and report an unknown outcome instead of cloning. 403 is a key or balance problem (Agents also use 402 for balance); read the body. Direct tool calls (`execute_tool`, REST, compiled and scheduled runs) are charged like agent runs; at an empty balance a paid call gets 402 `insufficient_balance` before it runs. 404 is an inaccessible ID, 409 an idempotency or state conflict, 400 field validation, 5xx retryable only when the operation is safe. Poll `/executions/{id}/status/?since=` (about 1 KiB) instead of full executions (about 67 KiB). Avoid account-wide lists in request paths, bound concurrency and timeouts, never use unbounded `asyncio.gather`, and cap files before decode. When live behavior conflicts with this file, make one bounded read-only probe and report the discrepancy. Codex and Cursor read `AGENTS.md`; Claude Code and Gemini CLI read a `CLAUDE.md` or `GEMINI.md` containing exactly `@AGENTS.md`. ## Release maintainers only A personal user connecting one account does not need to learn it. The release harness, before any product mutation, fetches `/agent-guide-release.json`, requires its `release_contract` with schema version 2, and compares it to an independently approved release pin; a candidate/stable mismatch stops the gate. Details: https://docs.flymy.ai/agents/guides/release-gates ### Release-maintainer-only connectionless fixture An assistant already building a requested worker must skip this entire section and publish that same requested agent - never a smoke agent beside it. The fresh-assistant gate also creates exactly one requested evaluation agent. The trusted release harness mints test customer IDs in its authenticated test identity store, never in prompts or MCP arguments.