{"ok":true,"message":"AgentStack MCP. Use POST /mcp for agentstack.execute or GET /mcp/discovery, /mcp/actions (full catalog), or /mcp/actions/summary (count only).","discovery":"/mcp/discovery","actions":"/mcp/actions","actions_summary":"/mcp/actions/summary","health":"/mcp/health","ai_prompt":"/mcp/ai_prompt","catalog_actions_public":752,"discovery_meta":{"transport":"streamable-http","execute_tool":"agentstack.execute","connect_help_uri":"https://agentstack.tech/mcp/connect","catalog_actions_public":752,"catalog_domains_public":59,"actions_summary_url":"/mcp/actions/summary","ai_prompt_url":"/mcp/ai_prompt","manifest_url":"/mcp/manifest","organs_url":"/mcp/organs","discovery_url":"/mcp/discovery","actions_url":"/mcp/actions","health_url":"/mcp/health","prompts_url":"/mcp/prompts/get","intent_url":"/mcp/discover/by_intent","recipes_url":"/mcp/recipes","oauth_connect_help_url":"/mcp/connect","oauth_authorize_well_known_url":"/.well-known/oauth-authorization-server/mcp","oauth_protected_resource_well_known_url":"/.well-known/oauth-protected-resource/mcp","oauth_authorize_path":"/mcp/.well-known/oauth-authorize","oauth_token_path":"/mcp/.well-known/oauth-token","oauth_browser_bridge_path":"/api/auth/mcp-oauth-bridge","prompts_available":true,"auth_modes":["api_key","bearer","oauth_well_known","oauth_ecosystem","device_code","mcp_auth_login"],"onboarding":{"session_setup_ladder":[{"phase":1,"id":"authenticate","title":"Authenticate","summary":"Establish MCP identity before any tenant mutation.","paths":[{"id":"oauth","label":"GPT / Cursor MCP Connector OAuth","note":"Connect in client — user logs in at agentstack.tech; Bearer carries user_id + RBAC."},{"id":"device_code","label":"Cursor / Claude IDE (Device Code)","note":"POST /api/oauth2/device/authorize — user approves at /activate; not browser MCP Connect."},{"id":"credentials","label":"In-band MCP login","actions":["auth.login","auth.register"],"note":"auth.login returns access_token — configure client Bearer before next batch."},{"id":"anonymous","label":"Greenfield sandbox","actions":["projects.create_project_anonymous"],"note":"Returns user_api_key + project_id once; configure client headers."}]},{"phase":2,"id":"project","title":"Select or create project","summary":"Every tenant resource lives under a project_id.","paths":[{"id":"list","label":"Existing account","actions":["projects.get_projects","projects.get_project"],"note":"Pick one workspace; remember project_id for later steps."},{"id":"create","label":"New workspace (signed in)","actions":["projects.create_project"]}],"recipe_id":"mcp_session_setup"},{"phase":3,"id":"bind_context","title":"Bind context.project_id","summary":"OAuth/Device Code often defaults to ecosystem project_id=1.","example":{"context":{"project_id":2048}},"prompt":"/mcp/prompts/get?name=agentstack_session_setup"},{"phase":4,"id":"domain_work","title":"Work Graph loop","summary":"Bound project: agents.work_next (recipe mcp_work_loop_v1) before catalog search. discovery.search is fallback only.","recipe_id":"mcp_work_loop_v1","note":"mcp_read_bootstrap is an optional read-only health check, not the first step."}],"session_setup_recipe":"mcp_session_setup","session_setup_prompt":"agentstack_session_setup","auth_methods":[{"id":"session_probe","label":"Session health check (after auth)","flow":"agentstack.execute","action":"auth.get_profile","aliases":["auth.me","auth.profile","auth.status","auth.whoami","auth.authenticate"],"note":"Confirm user_id and project context. REST GET /api/auth/me maps to the same MCP action; aliases auth.me, auth.profile, auth.status, auth.whoami resolve at runtime. discovery.health → system.ping; discovery.list_actions / discovery.actions → discovery.list; discovery.list_recipes → integrations.list_recipes; knowledge.list → knowledge.health."},{"id":"oauth_browser","label":"GPT / Cursor MCP Connector (recommended)","flow":"OAuth PKCE","authorize_url":"/mcp/.well-known/oauth-authorize","token_url":"/mcp/.well-known/oauth-token","connect_help_url":"/mcp/connect","note":"User signs in at agentstack.tech during Connect — token carries their user_id and RBAC. ChatGPT production OAuth requires login. Mobile/native return: GET /mcp/connect (connect_help_uri on OAuth metadata)."},{"id":"device_code","label":"IDE plugins (Device Code RFC 8628)","flow":"device_code","authorize_url":"/api/oauth2/device/authorize","token_url":"/api/oauth2/token","note":"Cursor/Claude Code: Connect in plugin UI or /agentstack-authorize — not MCP password grant."},{"id":"mcp_auth_login","label":"In-band MCP login","flow":"agentstack.execute","action":"auth.login","params":["email","password"],"note":"auth.login returns access_token — configure client Bearer before tenant work."},{"id":"api_key","label":"Personal API key","flow":"header","header":"X-API-Key","note":"When the client cannot complete OAuth (no browser, no connector), send the user's API key from the profile as X-API-Key or Authorization: Bearer. Scoped service_caps apply."}],"mandatory_order":["authenticate","project","bind_context","domain_work"],"anonymous_project":"POST /mcp with tool agentstack.execute — first step projects.create_project_anonymous","read_bootstrap_recipe":"mcp_read_bootstrap","read_bootstrap_options":{"continueOnError":true},"instruction_copy":{"avatar":"User avatar is POST /api/profile/avatar, field avatar. Check storage.list_files with project_id=1, scope=user, folder=ecosystem, and the URL on the profile. storage.upload does not become the avatar. auth.update_profile does not change the avatar. Profile JSON has a URL, never data: bytes.","scheduler":"scheduler.create_task recurrence is cron (minute hour day month weekday). timezone defaults to UTC and is stored for the next run. execute_at is one run and that task is removed after it fires. A cron without execute_at stays recurring.","stop_on_error":"Default stopOnError is true: steps after a failure are skipped. Recipe mcp_read_bootstrap sets continueOnError unless the request passes stopOnError.","session_workspace":"One identity session (one jti) covers every project membership allows. After auth.get_profile, if mutation_allowed or session_ready is true, set context.project_id only — do not call auth.switch_project and do not reconnect OAuth. There is no MCP tool context.set; pass params.project_id on each step instead. Switch + apply_bearer only when required_client_action is apply_bearer (project-scoped API key). Call auth.switch_project only when required_client_action is not none or mutation_allowed is false. Membership is projects.get_users, not projects.get_projects; jwt_project_mismatch is not logout. SPA and MCP OAuth Connect use session_type bearer_token (user-scoped). REST uses the same model: Bearer + X-Project-ID with server-side membership rebind.","hosting_file":"Site text edits: recipe mcp_hosting_edit_text_file_v1 or one hosting.bucket.file.patch (write_mode search_replace). The server refreshes the .gz sibling for nginx gzip_static and may cache_bust index.html — never bulk_delete .gz, never manual gzip. Omit bucket_id when hosting.project.status set primary_public_url. Not generation.fork. Omit generation_env_uuid on hosting.* byte writes — site edits do not fork. A stale uuid in batch context fails auto-fork; let the server keep the sandbox head. generation_fork_required on hosting.deploy_files is a status-projection defect: another generation.fork does not repair the bytes.","error_codes":"Trust step error_code: rag_embed_quota is embedding (not LLM provider_quota_exceeded). billing_service_unavailable / wallet_service_unavailable mean host dependency, not bad params. hosting.bucket.file.get 404 without a prior write in the batch is not_found, not not_ready. idempotency_conflict needs a new key or matching params. Integrations: duplicate_request, hook_verify_failed, hook_no_rule_match, connection_not_found, scenario_not_found, provider_not_found — not execution_error. Plan limits (rag_tier_limit, rag_embed_quota, sandbox_limit_exceeded, insufficient_permissions, buff_denied) include upgrade_url https://agentstack.tech/pricing and Compass playbook choose-billing-plane (task billing.choose_plan). list_unavailable means generation.list failed, not an empty project. parallel_canonical_drift means the sandbox would delete canonical money.expenses — realign, do not promote again. recipe_not_executable means run the phase recipe, not the template. auth.switch_project 401 project_session_required: authenticate (auth.login / auth.get_profile) — not global logout. 403 not_a_member / project_not_accessible: session stays valid; use projects.get_users; do not logout.","integrations":"Connect any API: integrations.list_recipes → integrations.connector_schema → install_recipe or create_connection → test_hook → connection_health. OAuth: oauth_begin. Recipe mcp_integrations_universal_connect_v1. Secrets in secrets= only.","outcome":"Preview is success with committed false. mcp_universal_safe_change is a non-executable template. mutation_allowed follows session_ready, not an infinite switch. Unknown scheduler commands save with runnable false. context.get source_status names rag_embed_quota for embeddings. agents.run_get uses the resource run_id; discovery.job_status polls MCP jobs. generation.list anchor_missing_from_list is stale: use generation.diff_vs_prod by UUID, not a new fork. Omit generation_env_uuid; the server keeps the sandbox head. That head is this user's latest open fork. Pass env_uuid only to read another person's fork. Stale generation_env_uuid (not found / not open) is cleared server-side and auto-fork retries — omit the uuid from context; do not fork again to repair. finance.expense writes canonical money.expenses, not the sandbox."},"domain_instruction_atoms":{"hosting":{"HOSTED_MCP_COOKIE":"Hosted /s/{pid}/mcp: session cookie aud=hosted_app with credentials:include — not operator MCP Bearer. POST /api/hosted-apps/{pid}/session mints the cookie.","MCP_OPERATOR_SESSION":"Operator MCP plane: X-API-Key or Bearer (Device Code OAuth). Bind context.project_id after auth.get_profile — not the hosted /s/ cookie.","HOSTING_BASE64_PADDING":"content_base64 validation_error: strip whitespace, add = until length % 4 — invalid padding fails before decode.","HOSTING_BASE64_DECODE":"Strip data: URL prefix; never pass PLACEHOLDER / YOUR_TOKEN literals as base64. Prefer UTF-8 content or hosting.bucket.file.patch search_replace over base64.","HOSTING_TEXT_EDITOR":"Text edits: hosting.bucket.file.patch write_mode=search_replace + replacements — same ladder as projects.patch_data and KB; prompt agentstack_text_editor.","HOSTING_REPLACE_SITE_CONFIRM":"replace_site=true wipes live pages — pass confirm_site_replace=true after dry_run. Default overlay: replace_site=false (merge upload).","HOSTING_GENERATION_ENV_OMIT":"Omit generation_env_uuid on hosting.* byte writes — site edits do not fork. A stale uuid in batch context fails auto-fork; let the server keep the sandbox head. generation_fork_required on hosting.deploy_files is a status-projection defect: another generation.fork does not repair the bytes.","HOSTING_STRICT_DIFF_HTML":".html/.htm unified_diff is strict (no fuzzy) by default — use search_replace for small edits or strict_diff=false only when hunks are exact.","HOSTING_BATCH_POLL_SAFE":"While orchestration lock is active, these reads may poll in the same batch without blocking mutations: hosting.project.status, hosting.bucket.file.get, hosting.bucket.files.list, hosting.site.edge_health, hosting.release.list, hosting.site.resolve. hosting.bucket.file.patch and hosting.deploy_files still require the lock to clear."},"hosting_when_blocked":{"site_not_found":"hosting.project.status — confirm primary site before file ops","validation_error":"content_base64: strip whitespace, pad to length % 4 — or use UTF-8 content / hosting.bucket.file.patch","replacement_not_found":"find absent in file — hosting.bucket.file.get(path) first; match exact bytes/whitespace; for title or large HTML blocks use write_mode=replace or hosting.files.put","ambiguous_anchor":"Multiple find matches — use a longer unique find or set count on the replacement pair","revision_conflict":"expected_sha256 mismatch — hosting.bucket.file.get then retry with fresh content_sha256","patch_apply_failed":"hosting.bucket.file.get, then search_replace or strict_diff=true","extension_not_patchable":"Text patch allows html, css, js, ts, json, md, txt, svg only","content_shrink_blocked":"allow_shrink=true when intentional, else search_replace for a partial edit","secret_pattern_blocked":"Remove API keys / bearer literals from site bytes — use hosted session cookie flow","preview_too_large":"Output >2MB — search_replace a section or hosting.deploy_files for large assets","invalid_path":"hosting.bucket.files.list — confirm path exists and suffix is patchable","hosting_snapshot_rate_limited":"Upload/publish succeeded; hourly snapshot cap hit — skip manual snapshot. Poll hosting.site.edge_health if the public URL is not ready.","hosting_replace_requires_confirmation":"replace_site=true requires confirm_site_replace=true — run dry_run first to preview paths","not_ready":"Batch write still projecting — poll hosting.bucket.file.get or hosting.bucket.files.list","not_found":"Path absent on bucket — hosting.bucket.files.list before patch","insufficient_permissions":"Project read or hosting operator required — auth.get_profile then rbac.check_permission","invalid_parameters":"project_id and bucket_id or bucket_name required for bucket file ops","bucket_id_or_bucket_name_required":"hosting.project.status — use primary_site_bucket_id or bucket_name; in a batch, pass bucket_id from the prior step result (refs) or primary_site_bucket_id; omit bucket_id only when primary or exactly one site exists; hosting.site.quick_start only when zero sites","bucket_not_found":"hosting.project.status — verify bucket_id/bucket_name; DNA/index drift — not quick_start if sites exist","release_not_found":"hosting.release.list — confirm release_uuid before delete or promote","release_pinned":"Unpin in UI or pick another release — pinned rows cannot be deleted","paths_or_prefix_required":"Pass paths[] or prefix — hosting.bucket.files.list to build the path set first","forbidden":"Ecosystem admin required — auth.get_profile for owner role"},"generation":{"GENERATION_ENV_OMIT":"Omit generation_env_uuid; the server keeps the sandbox head. That head is this user's latest open fork. Pass env_uuid only to read another person's fork.","GENERATION_STALE_ENV_UUID":"Stale generation_env_uuid (not found / not open) is cleared server-side and auto-fork retries — omit the uuid from context; do not fork again to repair.","GENERATION_ANCHOR_MISSING":"generation.list anchor_missing_from_list is stale: use generation.diff_vs_prod by UUID, not a new fork.","GENERATION_LIST_STALE":"generation.list list_stale: retry generation.list once (project_id only), then generation.diff_vs_prod. Do not fork to repair projection lag.","GENERATION_LIST_UNAVAILABLE":"list_unavailable means generation.list failed, not an empty project — retry once, then diagnose; do not fork to fill the list.","GENERATION_SANDBOX_QUOTA_ZERO":"Sandbox unavailable or quota zero — do not invent env_uuid; upgrade tier / free anchors via generation.list, then fork only when list succeeds with room.","GENERATION_PARALLEL_DRIFT":"parallel_canonical_drift blocks promote when the sandbox would delete canonical money.expenses — generation.realign_to_prod, do not promote again.","GENERATION_REALIGN_DRY_RUN":"Discard sandbox edits — generation.realign_to_prod dry_run first; path_prefixes for partial revert; not a substitute for promote.","GENERATION_SAFE_CYCLE_LADDER":"auto_generation_mode on: mutate auto-forks sandbox → generation.diff_vs_prod → generation.gates → generation.promote (auto_promote_strategy). No prod dna_set_* / leaf writes without sandbox anchor — not deploy scripts.","GENERATION_DIRECT_PROD":"direct_prod_roles (default owner) write production and skip auto-fork. Everyone else accumulates on their own open sandbox branch. Pass env_uuid or X-AgentStack-Env only to stay in a chosen sandbox.","GENERATION_APPROVAL_MODES":"auto_generation_approval_mode: off | at_least_one | min_count | min_percent | manual_only. manual_only blocks auto-promote. generation.approve records one approver; promote waits until quorum. Legacy require_approval true means at_least_one.","GENERATION_CANARY_LADDER":"Canary traffic is generation.canary.advance / generation.canary.abort on a rolling_out anchor. Strategy comes from auto_promote_strategy — do not invent weights.","GENERATION_CHECKPOINT_LADDER":"generation.checkpoint snapshots merged DNA. generation.rollback opens that checkpoint as a new draft sandbox. Restore prod only via generation.promote.","GENERATION_DISCARD":"generation.discard is generation.realign_to_prod with dry_run default true. Pass source_revision from the last diff. dry_run=false applies the revert.","GENERATION_HOSTING_RELEASE":"generation.hosting.release moves a site release pointer. Site bytes stay on hosting.bucket — this tool does not fork 8DNA.","GENERATION_NOTIFY":"generation.notify pings operators about a sandbox anchor. It does not promote, approve, or change DNA."},"generation_plane_chooser":"Sandbox: omit generation_env_uuid; the server keeps the sandbox head. That head is this user's latest open fork. Pass env_uuid only to read another person's fork. A CRM or scheduler read stays on that category's fork for this user. Empty generation.list is not zero anchors. list_unavailable is a failed read. A pointer that is not an anchor row leaves the catalog empty. diff_vs_prod still reads it. Do not call generation.fork to fill the list. diff_vs_prod, gates, promote. Strategy is auto_promote_strategy. Site bytes do not fork. parallel_canonical_drift: realign, do not promote.","generation_env_parity":"Omit generation_env_uuid — server keeps sandbox head; stale uuid is cleared automatically.","ai_builder":{"AI_BUILDER_LIST_ALIAS":"ai_builder.project.list aliases to ai_builder.source.list — list App Studio src/** paths, not hosting bucket bytes.","AI_BUILDER_SOURCE_VS_HOSTING":"App Studio source tree is ai_builder.source.* under src/** — static /s/ bytes are hosting.bucket.file.patch, not ai_builder.source.patch on the live bucket.","AI_BUILDER_PUBLISH_BOUNDARY":"ai_builder.publish omits bucket_id when hosting.project.status shows primary_public_url. Do not hand-edit assets/index-*.js build output. If bucket_id_or_bucket_name_required — run hosting.site.quick_start first (or pass bucket_id from hosting.project.status).","AI_BUILDER_HOSTED_SESSION":"Published pages call /s/{project_id}/mcp with credentials on load — not MCP auth.login for visitors; clearSession only on HTTP 401.","AI_BUILDER_BUILD_FAILED_RECOVERY":"Vite parse error in errors[0].file:line. source.get view=symbol, source.patch once, build.enqueue again. Browserslist/caniuse warnings are not failures.","AI_BUILDER_PROTECTED_PATHS":"Do not patch vite.config.ts, package.json, index.html, src/main.tsx, or src/styles/app.css. Edit @slot: regions in src/routes/Route0.tsx. Browserslist noise is not a build failure.","AI_BUILDER_LITERAL_ESCAPE":"literal_escape: use symbols:[{name, replace}] with real newlines in replace bodies — not \\\\n in JSON strings. Prefer symbol edits over full-file content rewrites.","AI_BUILDER_RECIPE_NOT_TOOL":"mcp_app_studio_* are recipes (executable=false) — run via recipe runner or ai_builder.compose.apply / build.enqueue, not agentstack.execute with recipe id as action."},"logic":{"LOGIC_DRY_RUN_FIRST":"logic.create / logic.attach_template mutations: logic.dry_run with logic_id before enable or production traffic. Disabled rules still dry-run. A space graph with processors must execute; blocks_executed=0 is no_blocks_executed, not success.","LOGIC_ID_FROM_RECEIPT":"logic.dry_run needs logic_id from logic.create or logic.attach_template receipt — not a rule spec or template_id alone.","LOGIC_NO_SECOND_CREATE":"Do not logic.create a second rule — logic.get the id from the first create receipt.","LOGIC_ATTACH_TEMPLATE_CATALOG":"logic.attach_template: template_id from the built-in catalog — wrong id returns not_found; prefer attach_template over hand-copying blocks.","LOGIC_VERSION_CONFLICT":"logic.restore_version / logic.diff_versions: logic.list_versions first — stale version_id returns not_found; diff before restore.","LOGIC_COLLECTION_EMPTY_BLOCKED":"logic.update with empty triggers/space/schedulers is blocked (logic_collection_empty_blocked) — use write_mode intentionally."},"logic_plane_chooser":"logic.create or logic.attach_template from catalog, then logic.dry_run before enabling on production traffic. logic.dry_run needs logic_id from the create/attach receipt — not a rule spec or template_id alone. Empty logic.list is this user's logic fork, else the live head. Do not logic.create a second rule — logic.get the id from the first receipt. Version history: logic.list_versions → logic.diff_versions → logic.restore_version. Integration Hub recipes may attach rules — do not duplicate inbound intake with a second logic.create.","logic_when_blocked":{"logic.create":{"invalid_parameters":"logic.get_commands + logic.signals_catalog before triggers/space","invalid_structure":"logic.get_processors for processor ids — fix graph before retry","processor_not_found":"logic.get_processors — specified processor not available","insufficient_permissions":"logic_write cap + project membership on tenant PID"},"logic.attach_template":{"not_found":"template_id from built-in catalog — verify id before attach_template","invalid_parameters":"context.project_id bound — template_id required","internal_error":"logic.list — reuse logic_id or logic.create with template blocks"},"logic.dry_run":{"not_found":"logic.list or logic.get — logic_id from create/attach receipt","invalid_parameters":"logic_id required — not template_id or inline rule spec","logic_execution_failed":"logic.get graph — fix processor ids via logic.get_processors","no_blocks_executed":"space has processors but none ran — logic.get the graph; dry_run is not a no-op"},"logic.update":{"logic_not_found":"logic.list or logic.get with same project_id before update","logic_collection_empty_blocked":"pass write_mode or non-empty collection — not wipe","write_mode_invalid":"logic.get_commands — supported write_mode for triggers/space","write_mode_unsupported":"append/prepend are not valid for logic collections","replacement_not_found":"replacements.find is not in text_field (description|name)","patch_apply_failed":"unified_diff did not apply on text_field — logic.get and retry","content_shrink_blocked":"full replace on text_field is much shorter — allow_shrink or search_replace","insufficient_permissions":"logic_write cap + project membership"},"logic.list_versions":{"not_found":"logic.list or logic.get — logic_id from create/attach receipt","invalid_parameters":"logic_id required — not template_id"},"logic.diff_versions":{"not_found":"logic.list_versions — pick two version ids from history","invalid_parameters":"logic_id and from_version/to_version required"},"logic.restore_version":{"not_found":"logic.list_versions — version_id must exist on logic_id","version_conflict":"logic.diff_versions first — CAS revision mismatch on restore","invalid_parameters":"logic_id + version_id required"},"logic.export_json":{"not_found":"logic.list or logic.get — export needs logic_id","invalid_parameters":"logic_id required"},"logic.import_json":{"invalid_parameters":"rule JSON body + logic_id or create path — logic.dry_run after import","invalid_structure":"logic.get_commands — processor ids must exist in project"},"logic.install_blueprint":{"not_found":"catalog blueprint id — prefer logic.attach_template when id known","invalid_parameters":"blueprint_id + project_id required"},"logic.get":{"not_found":"logic.list — logic_id from create/attach receipt","logic_not_found":"logic.list — logic_id from create/attach receipt","project_not_found":"bind context.project_id before logic.get","invalid_parameters":"logic_id + context.project_id required","internal_error":"retry once; logic.list if logic_id may be stale"},"logic.list":{"invalid_parameters":"context.project_id bound — optional filters only","unauthorized":"logic_read cap + project membership"},"logic.execute":{"not_found":"logic.get — rule must exist; logic.dry_run before production execute","logic_not_found":"logic.list — logic_id from create/attach receipt","logic_execution_failed":"logic.get_processors — fix graph before execute","execution_failed":"Rule execution failed — logic.get graph before retry","invalid_parameters":"logic_id + command_data required"},"logic.get_processors":{"invalid_parameters":"context.project_id bound","unauthorized":"logic_read cap before planning processors"},"logic.get_commands":{"invalid_parameters":"context.project_id bound","unauthorized":"logic_read cap — catalog of block commands"},"logic.flush_batch":{"invalid_parameters":"batch scope + project_id required","not_found":"no pending batch — logic.list or prior flush receipt","project_not_found":"bind context.project_id before logic.flush_batch","internal_error":"retry once; logic.list if batch state unknown"},"logic.signals_catalog":{"invalid_parameters":"context.project_id bound","unauthorized":"logic_read cap before wiring triggers"},"logic.mcp_actions_catalog":{"invalid_parameters":"context.project_id bound","unauthorized":"logic_read cap — processor action catalog"},"logic.delete":{"not_found":"logic.list — logic_id must exist before delete","logic_not_found":"logic.list — logic_id must exist before delete","insufficient_permissions":"logic_write cap + project membership","invalid_parameters":"logic_id + context.project_id required"}},"work_graph":{"WG_OPTIMIZE_EXEC_STABLE":"optimize_plan must not change executable_now unless patches touch required_role, skill_ids, or completion criteria — check validation.execution.execution_summary.","WG_ALLOW_GENERIC_ACCEPTANCE":"allow_generic_acceptance defaults false; repair_plan / sandbox repair only — never default on complexity ≥3 decompose.","WG_EXECUTION_SUMMARY_ONLY":"Read execution_summary.missing_requirements — missing_roles is legacy; do not infer fleet gaps from validation.missing_roles when execution_summary is present.","WG_CLAIM_PREVIEW_SINGLE":"plan_get include_claimable=true — each claim preview row.execution from one canonical execution-resolver pass (execution_resolver SoT).","WG_ENV_UUID_PARITY":"Thread the same env_uuid across plan_get, plan_propose, plan_apply_proposal, plan_process_backlog, plan_recovery_scan, and work_next on sandbox forks.","WG_RECOVERY_VERIFICATION_FAILED":"Recovery reason SoT is verification_failed (aliases verify_failed, plan_verify_failed) — call agents.plan_recovery_scan first, then plan_propose mode=repair_plan via recovery.next_actions (not missing_roles).","WG_BLOCKED_REASON":"blocked_work[].blocked_reason is canonical (block_reason.REASON_PRIORITY); use recovery.next_actions — not validation.missing_roles.","WG_PROVISION_PARITY":"When execution.fully_provisionable and one top template, recovery routes agents.ensure_agent create=false (H5 preview) — SDK followWorkGraphAction runs ensureAgentSaga for create=true; ambiguous ties → create_from_template choose_template.","WG_ENSURE_H5":"agents.ensure_agent preview template_id must match agents.work_next top compatible_templates[0] for the same node (harness H5 / resolver_parity_v1).","WG_FACET_REPAIR":"plan_propose runs ensure_proposal_facet_coverage (facet_repair, max 2 passes) after enrich for create_plan and decompose_node (including from_draft_tree meta under create_plan) — do not hand-patch semantic facet children; for facet gaps after other modes use mode=repair_plan.","WG_REPAIR_METRICS_SCAN_COUNTS":"plan_recovery_scan meta.repair_metrics is scan summary only (candidate_count, stale_claim_count). Facet repair_metrics (nodes_created, repair_graph_edit_distance) and repair_diagnostics come from plan_propose mode=repair_plan — not from scan counts.","WG_HARNESS_GATES":"Dev gates: doctor --full (repo.ops.closed_loop.harness.gen1); key suites: ensure_agent_provision_e2e_v2, ensure_agent_idempotent_retry_v1, bind_vs_claim_semantics_v1, persist_unexecutable_v1, mcp_structured_domain_error_v1, resolver_parity_v1, instruction_plane_dry_v2, planner_runtime_parity_v3.","WG_BIND_VS_CLAIM":"node.agent_id binding ≠ active claim lease — already_claimed requires status=in_progress with non-expired lease meta; bound agent on ready/pending is not already_claimed; retry ensure_agent idempotent_replay or plan_claim with if_match_revision.","WG_HARNESS_STATE":"Blocked agents.work_next packets include diagnostics.harness_state — read-only projection (dependency_ready, execution_ready, blocked_reason); not a second orchestrator.","WG_ROLE_TAXONOMY":"no_compatible_agent for role=data|data_engineer is a taxonomy alias — prefer agents.ensure_agent create=false (H5) then create=true before repair_plan; create_from_template only when ensure_agent is ambiguous; role_matches_template in role_taxonomy.py is SoT.","WG_TEAM_OVER_INTEGRATION":"Team-create goals (agents.team.create): discovery rank demotes integrations.* — prefer agents.team.create / agents.orchestrate / agents.plan_* over integrations.oauth_begin.","WG_CLAIM_BEFORE_EXECUTE":"agents.plan_execute requires an active claim lease from agents.plan_claim unless operator policy allows execute-without-claim; pass if_match_revision from plan_get.","WG_AUTONOMOUS_CLAIM_REQUIRED":"When context.autonomous_mode is true, agents.plan_execute is denied unless the focus node status is in_progress (plan_claim_required). Claim via agents.plan_claim before execute in the mcp_work_loop_v1 spine.","WG_PERSIST_UNEXECUTABLE":"validation_mode=persist_unexecutable on plan_propose / plan_apply_proposal / plan_process_backlog when plan_valid but fleet cannot execute — use the same mode on propose and apply.","WG_PLAN_VALID_NOT_EXECUTABLE":"plan_valid / validation_ok means structural+semantic OK — not fleet-executable; use validation_mode=persist_unexecutable or ensure_agent when plan_valid but not execution_ready; executable_now=false under semantic alias is intentional.","WG_CAPABILITY_HARD_GATE":"required_capabilities are mandatory — capability_mismatch blocks claim; route agents.ensure_agent create=false (H5) then create=true, or plan_propose mode=repair_plan; not handoff (capability_hard_gate_v1).","WG_PLANNING_ARTIFACT":"meta.planning_artifact nodes are evidence-only (resolution=non_executable_artifact) — attach evidence on parent; plan_process_backlog and claim skip them for execution.","WG_ENSURE_CREATE_SAGA":"Commit-last provision: work_next blocked → ensure_agent create=false (H5 template_id) → create=true provisions with bind_node=False → eligibility gate → rollback on created_agent_not_eligible → next_action agents.plan_claim (bind+lease, if_match_revision); idempotent_replay when bound eligible agent exists.","WG_HANDOFF_RECOVERY":"role_mismatch / specialization_mismatch after claim → work_next handoff=true node_id=… — follow recovery.next_actions, do not retry same agent. capability_mismatch is missing required_capabilities: repair_plan or ensure_agent, not handoff.","WG_CAS_RETRY":"plan_revision_conflict → plan_get reload if_match_revision — never apply stale proposal after concurrent plan_patch or backlog apply.","MCP_DOMAIN_ERROR":"Domain denial: tools/call isError=false with structuredContent (ok=false, error_code, failure_kind=domain, recovery). Transport/internal uses isError=true (failure_kind=transport). plan_revision_conflict → agents.plan_get then retry with fresh if_match_revision.","WG_CLOSED_LOOP_EXECUTABLE":"state=actionable (alias executable) and execution_ready — next_action agents.plan_claim with if_match_revision from plan_get.","WG_CLOSED_LOOP_PROVISION":"resolution=provision_required — next_action agents.ensure_agent create=false (H5) then create=true before plan_claim.","WG_CLOSED_LOOP_STALE_CLAIM":"blocked_reason=expired_claim — next_action agents.plan_reclaim_stale; beats downstream dependency_blocked when no executable leaf.","WG_CLOSED_LOOP_PLANNING":"planning_required — next_action agents.plan_propose mode=create_plan or decompose_node.","WG_CLOSED_LOOP_VERIFY_FAIL":"verification_failed — next_action agents.plan_recovery_scan then repair_plan.","WG_CLOSED_LOOP_DEPENDENCY":"dependency_blocked — no claim; reason names upstream node_id until deps complete.","AGENTSTACK_NATIVE_FIRST":"Before custom servers: discovery.search → domain workflow → MCP/SDK configure → verify via canonical read. Frontend consumes @agentstack/sdk — not operator Bearer.","WG_STORAGE_NOT_KNOWLEDGE":"File upload / document persistence → storage.* (MCP operator or REST binary upload). Do not ingest to knowledge unless the goal requests RAG/Q&A/semantic search.","WG_MCP_SDK_REST_PLANE":"MCP: operator/agent configure + work graph. SDK: app runtime integration. REST: binary transfer or capability not in SDK. Never duplicate platform CRM/Auth/Storage.","WG_VERIFY_AFTER_WRITE":"After each platform mutation, verify via canonical read on meta.verify_after_write_action (storage.list_files, crm.list_contacts, logic.dry_run, rag.search) — attach evidence, do not mark complete from agent prose alone.","WG_PLAN_GRAPH_CHILDREN_CAP":"Max 32 direct children per parent_id (not total graph size). Large flat graphs are valid; split siblings across intermediate feature nodes when one parent exceeds the cap.","WG_PLAN_FIRST":"Lightweight progress: agents.work_status (summary_only). Full autonomous loop: agents.work_next — follow next_action, not next_actions[0] parsing.","WG_GRAPH_FOR_DURABLE_WORK":"Durable work (more than one read) enters the Work Graph: agents.plan_propose (create_plan or decompose_node), agents.plan_apply_proposal when validation.safe_to_auto_apply, then agents.work_next following next_action until state=idle, blocked, or recoverable. A single domain call (one CRM write, one file upload, discovery.search, auth.get_profile) stays a direct MCP action. Do not mark a node complete from prose — attach meta.verify_after_write_action evidence. Idle with an empty graph is valid.","WG_WORK_NEXT_LOOP":"Closed loop: plan_get → work_next → next_action → execute/claim → work_next until state=idle. Blocked: read recovery.next_actions or singular next_action.","WG_LOOP_ERROR_BUDGET":"Loop error budget (WG-SLO-03/04): follow packet.next_action from agents.work_next — discovery.search while next_action is present burns compliance (target ≥90% followed). Heavy batches: options.async=true; full budget GET /mcp/actions execute_budget.","WG_PLAN_EXECUTE_HANDOFF":"After agents.plan_execute success (wait=true completed), follow data.next_action (usually agents.work_next) — do not invent a parallel loop from prose.","WG_PLANNER_PLANE":"Backlog scan uses planner eligibility (decomposition_status=needed) — not execution_ready; validation_ok reflects plan_valid (structural+semantic), not fleet gaps.","WG_GUIDANCE_LIST":"Before work-graph execution: guidance.list to confirm work-graph-agent-loop in catalog; guidance.match_playbook with closed-loop goal_text; guidance.start_path with catalog_entry.id from match.","WG_DISCOVERY_ROUTE":"Discovery naming: intent_id (taxonomy) ≠ primary_action (router verb) ≠ agents.work_next (fleet pick) — do not treat a route phrase as an MCP action name. discovery.describe requires param action=<catalog action id> (not optional).","WG_DEPENDENCY_VS_EXECUTION_READY":"dependency_ready is structural (deps/status/decomposition); execution_ready is fleet (live agent or provision path) — never collapse the two gates.","WG_COLD_START_VS_ROUTE":"Cold start: no project_id → agentstack_session_setup only. Do not discovery.search until context.project_id is set. Bound project: agents.work_next first; discovery.search only when packet.next_action is absent. Status-only poll → agents.work_status (no claim params)."},"work_graph_plane_chooser":"Plan graph: agents.plan_get with project_id. Next leaf: agents.work_next — read dependency_ready vs execution_ready separately. dependency_ready=false means wait on deps; execution_ready=false with dependency_ready=true means fleet/provision. Draft changes: agents.plan_propose then agents.plan_apply_proposal (same env_uuid). Claim: agents.plan_claim with if_match_revision from plan_get. Blocked with templates: agents.ensure_agent (preferred) then agents.create_from_template — not a second custom resolver.","support":{"SUPPORT_USER_VS_STAFF":"End users: social.support.history / social.support.send on psup_p{pid}_u{uid}. Staff desk: social.support.inbox / transition / assign — not social.chat.*.","SUPPORT_ELIGIBILITY_FIRST":"social.support.eligibility before history/send — end_user_support_enabled false returns eligibility_denied on user-plane reads.","SUPPORT_AI_BINDING":"social.support.config.patch binds one project agent — confirm with social.support.ai_binding_health; channel_not_bound when ai_agent_uuid missing.","SUPPORT_NOT_CHAT":"Support threads are social.support.* — social.chat.history is messenger DMs, not psup tickets."},"support_plane_chooser":"User plane: social.support.eligibility → social.support.history / social.support.send. Staff plane: social.support.inbox — requires support desk access on the project. Messenger DMs use social.chat.*; support tickets use social.support.*, not social.chat.history.","commerce":{"CHECKOUT_TIER_GATE":"payments.create blocked by feature gate — buffs.get_effective_limits; payments.get_balance and payments.list_methods before retry.","ASSETS_SANDBOX_HEAD":"Empty assets.list after assets.create is the sandbox head — server keeps the row; do not patch data.assets.items[] manually.","PAYMENTS_NO_LIST":"payments.list does not exist — use payments.get_balance, payments.get, or wallets.list.","WALLET_VS_CHECKOUT":"Wallet moves use wallets.deposit / wallets.transfer — AgentPay checkout is payments.create.","COMMERCE_BUFFS_LINK":"Tenant subscription checkout auto-grants via webhook/C24 — not buffs.apply_buff after payments.create."},"commerce_plane_chooser":"Money: payments.get_balance and wallets.list. Checkout is AgentPay via payments.create — chain payments.get for status. Catalog: assets.list → assets.create — do not replace data.assets.items[]. Empty list after create is the sandbox head. Tier gates: buffs.get_effective_limits before retrying checkout or assets_write.","commerce_when_blocked":{"payments.create":{"service_cap_denied":"apikeys.create with payments in service_caps — operator key lacks payments cap","feature_gate_denied":"buffs.get_effective_limits — plan tier blocks checkout; upgrade_url or buffs grant","invalid_parameters":"payments.get_balance first — amount, currency, method_id required for AgentPay","insufficient_permissions":"project write + payments cap on tenant PID","invalid_amount":"payments.get_balance — amount must be positive major units","invalid_currency":"payments.list_methods — currency code from supported methods","preferred_method_required":"payments.list_methods — pass preferred_method from catalog","unsupported_payment_method":"payments.list_methods — pick a method enabled for this PID","execution_error":"payments.get_balance then retry same idempotency_key; diagnose if repeats"},"payments.get":{"not_found":"payment_id from payments.create receipt — payments.list_transactions audit","payment_not_found":"payments.list_transactions — payment_id from payments.create receipt","invalid_parameters":"payment_id UUID required — not order slug or asset id","insufficient_permissions":"project membership with payments:read"},"payments.get_balance":{"service_cap_denied":"payments cap on API key — widen service_caps or use session auth","insufficient_permissions":"project membership with payments:read","project_not_found":"context.project_id bound — projects.list for a valid PID","wallet_not_found":"wallets.list — create wallet via wallets.create before reading balance"},"payments.list_transactions":{"insufficient_permissions":"project membership with payments:read","project_not_found":"context.project_id bound — projects.list for a valid PID"},"payments.refund":{"not_found":"payments.get with payment_id — reverse only after wallet_credit=ok","payment_not_found":"payments.get with payment_id from checkout receipt","invalid_parameters":"payment_id + amount from payments.get status","insufficient_permissions":"payments write cap + project admin","refund_exceeds_capture":"payments.get — partial amount must be ≤ captured major units","refund_in_progress":"Retry with same idempotency_key or poll payments.get","refund_not_allowed":"payments.get status — refund only after capture succeeded","refund_seller_debit_required":"commerce.refund.status — seller debit plane before refund"},"assets.create":{"service_cap_denied":"apikeys.create with assets_write in service_caps","insufficient_permissions":"project write + assets_write cap","unknown_preset":"assets.list_presets — preset slug from catalog row","creation_failed":"generation sandbox head may apply — assets.list before second create","name_required":"name is required — assets.list_presets for a starter row","invalid_type":"type must be a known asset type — assets.list_presets","invalid_structure":"components must match preset schema — assets.list_presets"},"assets.get":{"asset_not_found":"assets.list — opaque asset_id as returned by create/list"},"assets.update":{"asset_not_found":"assets.list or assets.get — confirm asset id on active sandbox head","insufficient_permissions":"assets_write cap + project membership","invalid_parameters":"patch leaf paths only — not full data.assets.items[] blob","invalid_structure":"assets.get then patch leaf paths valid for the asset type"},"assets.delete":{"asset_not_found":"assets.list — check storefront refs before delete","insufficient_permissions":"assets_write cap required","project_id_required":"context.project_id bound — pass project_id on delete"},"assets.list":{"project_id_required":"context.project_id bound — empty list may be sandbox head not zero catalog"},"wallets.create":{"invalid_parameters":"wallets.list — project_id, currency, and wallet_id params required","wallet_service_unavailable":"Backoff then retry; agentstack_diagnose if it persists"},"wallets.list":{"invalid_parameters":"wallets.list — project_id, currency, and wallet_id params required","wallet_service_unavailable":"Backoff then retry; agentstack_diagnose if it persists"},"wallets.transfer":{"invalid_parameters":"wallets.list — project_id, currency, and wallet_id params required","wallet_service_unavailable":"Backoff then retry; agentstack_diagnose if it persists"},"wallets.deposit":{"invalid_parameters":"wallets.list — project_id, currency, and wallet_id params required","wallet_service_unavailable":"Backoff then retry; agentstack_diagnose if it persists","invalid_amount":"amount must be positive — wallets.list for balance first","wallet_not_found":"wallets.list — wallet_id before deposit; wallets.create if none"},"commerce.participant.grant_holding":{"invalid_project":"Bind context.project_id or pass project_id (>1 tenant PID)","forbidden":"auth.get_profile — operator session required","grant_failed":"assets.list — confirm asset_id; buffs path for subscription SKUs","insufficient_permissions":"require_tenant_project_write — project admin on tenant PID"},"commerce.refund.status":{"not_found":"commerce.refund.status with buyer_project_id, buyer_user_id, order_id","forbidden":"ecosystem_owner_required for manual refund plane","invalid_parameters":"buyer_project_id, buyer_user_id, order_id required"},"commerce.refund.manual_list":{"ecosystem_owner_required":"Finances / ecosystem owner session — not tenant buyer","forbidden":"auth.get_profile then ecosystem admin role"},"commerce.refund.psp_refund":{"ecosystem_owner_required":"Finances / ecosystem owner — seller claw + PSP","order_not_found":"commerce.refund.status — verify buyer_project_id, buyer_user_id, order_id","rail_not_fiat":"Wallet rail auto-compensates — no PSP step","no_payment_id":"Order metadata.payment_id missing — payments.get from checkout receipt","refund_in_progress":"Retry with same idempotency_key or poll payments.get","refund_exceeds_capture":"Partial amount must be ≤ captured major units"},"commerce.refund.manual_complete":{"ecosystem_owner_required":"Same as manual_list — operator refund completion","not_found":"commerce.refund.manual_list row id"},"commerce.storefront.list":{"invalid_parameters":"project_id required — catalog before seed_apply","insufficient_permissions":"project read + commerce caps"},"commerce.storefront.hosted_publish":{"invalid_parameters":"user_id + project_id — build dist before publish","publish_failed":"commerce.storefront.health — bucket + hosted manifest"},"commerce.ai.generate_products":{"rate_limited":"Backoff — tier limits via buffs.get_effective_limits","invalid_parameters":"project_id + prompt constraints from assets.list"},"commerce.ai.magic_fill":{"invalid_parameters":"asset id or draft row from assets.create","feature_not_available":"Plan tier — buffs.get_effective_limits"},"commerce.sell.activate":{"forbidden":"Tenant operator — commerce.sell.activate vs buffs.grant","invalid_parameters":"SKU / activation payload from storefront list"},"commerce.reconcile":{"forbidden":"Ecosystem owner — finances PID plane","invalid_parameters":"date range + project scope"}},"crm_plane_chooser":"Contacts: crm.list_contacts / crm.search → crm.upsert_contact (dedupe by email). Deals: crm.create_deal after contact exists → crm.list_board before crm.move_deal_stage. Bulk: crm.import_contacts for CSV ingest — crm.merge_contacts for duplicate rows. Timeline: crm.get_contact_360 / crm.get_deal_timeline after writes. Sandbox reads: pass effective_scope.env_uuid after tenant promote — empty list is the head.","crm_when_blocked":{"crm.upsert_contact":{"duplicate_contact":"crm.list_contacts by email — merge via crm.merge_contacts or set external_id on update"},"crm.import_contacts":{"import_blocked":"crm.list_contacts to preview dupes — shrink batch or crm.merge_contacts before retry"},"crm.update_deal":{"pipeline_stage_locked":"crm.list_board + crm.get_crm_config — use crm.move_deal_stage for stage changes"},"crm.move_deal_stage":{"pipeline_stage_locked":"crm.list_board + crm.get_crm_config — verify stage_id before move"}},"platform":{"BATCH_DEPENDS_ON_DEFAULTS":"agentstack.execute steps: omit dependsOn for independent lanes; set dependsOn to prior step ids for DAG order. continueOnError defaults false — failed step skips dependents (plain reads may continue per mixed-batch policy). See agentstack-work-graph skill.","DOCS_NAV_NOT_MCP_TOOLS":"docs_nav.search indexes markdown and genetic tags for docs routing only — not MCP capability discovery. Runtime tools: discovery.search, discovery.list, POST /mcp/discover/by_intent.","PREFLIGHT_BEFORE_MUTATE":"Effect medium+ or financial/destructive: run preflight.check with context.project_id bound before mutate. session_ready and service_caps surface in preflight — not retry loops."},"diagnostics":{"DIAG_CAPABILITIES_SPLIT":"Operator REST: GET /api/diagnostics/capabilities/flags (lightweight) vs /capabilities/observability?since= (heatmap). Full GET /capabilities composes both — prefer split routes on admin hub tabs.","DIAG_HUB_ETAG":"Admin hub GET /api/admin/hub-snapshot returns weak ETag — send If-None-Match for 304. Default source=shell is counts-only; source=full for legacy DNA totals.","DIAG_PROBLEMS_CACHE":"Problems cache TTL 30s aligned with hub. Prefer hub problems_summary for counts; full GET /api/diagnostics/problems only on expand.","DIAG_HUB_PHASES":"Admin hub fetch uses sequenced phases — shellBeacons admin_hub_phase_start/done with duration_ms for triage.","DIAG_SHOWCASE_WARM":"Showcase-excl count projector warms at startup (300s TTL); commerce T0 KPI warm pairs with hub cold path.","context_source_routing_drift":"context.get requested sources do not match source_status rows — check tools_context._parse_sources and ContextFabric gather (no silent RAG substitution for crm).","specialization_strategy_conflict":"Work graph nodes carry custom_backend_engineer on agentstack_native facets — recompile per-facet implementation_mode in node_semantic_compiler.","sync_async_latency_divergence":"Sync agentstack.execute exceeded 30s or diverged from durable/async baseline — use options.async=true or reduce expensive steps per batch (execute_budget)."},"admin_platform_perf":{"DIAG_CAPABILITIES_SPLIT":"Operator REST: GET /api/diagnostics/capabilities/flags (lightweight) vs /capabilities/observability?since= (heatmap). Full GET /capabilities composes both — prefer split routes on admin hub tabs.","DIAG_HUB_ETAG":"Admin hub GET /api/admin/hub-snapshot returns weak ETag — send If-None-Match for 304. Default source=shell is counts-only; source=full for legacy DNA totals.","DIAG_PROBLEMS_CACHE":"Problems cache TTL 30s aligned with hub. Prefer hub problems_summary for counts; full GET /api/diagnostics/problems only on expand.","DIAG_HUB_PHASES":"Admin hub fetch uses sequenced phases — shellBeacons admin_hub_phase_start/done with duration_ms for triage.","DIAG_SHOWCASE_WARM":"Showcase-excl count projector warms at startup (300s TTL); commerce T0 KPI warm pairs with hub cold path.","context_source_routing_drift":"context.get requested sources do not match source_status rows — check tools_context._parse_sources and ContextFabric gather (no silent RAG substitution for crm).","specialization_strategy_conflict":"Work graph nodes carry custom_backend_engineer on agentstack_native facets — recompile per-facet implementation_mode in node_semantic_compiler.","sync_async_latency_divergence":"Sync agentstack.execute exceeded 30s or diverged from durable/async baseline — use options.async=true or reduce expensive steps per batch (execute_budget)."},"session":{"HOSTED_MCP_COOKIE":"Hosted /s/{pid}/mcp: session cookie aud=hosted_app with credentials:include — not operator MCP Bearer. POST /api/hosted-apps/{pid}/session mints the cookie.","MCP_OPERATOR_SESSION":"Operator MCP plane: X-API-Key or Bearer (Device Code OAuth). Bind context.project_id after auth.get_profile — not the hosted /s/ cookie."}},"prompts":{"system":"agentstack_system_instructions","session_setup":"agentstack_session_setup","safe_project_cycle":"agentstack_safe_project_cycle","closed_loop_autonomy":"agentstack_closed_loop_autonomy","work_graph":"agentstack_work_graph","inverse_orchestrator_playbook":"agentstack_inverse_orchestrator_playbook","tenant_8dna_supply":"agentstack_tenant_8dna_supply","read_bootstrap":"agentstack_read_bootstrap","hosting_static_landing":"agentstack_hosting_static_landing","hosting_react_dist":"agentstack_hosting_react_dist","hosting_file_edit":"agentstack_hosting_file_edit","execute_budget":"agentstack_execute_budget","write_modes":"agentstack_write_modes","text_editor":"agentstack_text_editor","kb_chunk_edit":"agentstack_text_editor","api_key_safety":"agentstack_api_key_safety"},"recipes":[{"id":"mcp_session_setup","label":"Auth + list projects (mandatory before tenant work)"},{"id":"mcp_work_loop_v1","label":"Work Graph agent loop (work_next → claim → execute)"},{"id":"mcp_read_bootstrap","label":"Read-only bootstrap (profile, limits, quota)"},{"id":"mcp_hosting_quickstart","label":"Publish a hosted site (/s/ URL)"},{"id":"mcp_integrations_checkout_crm","label":"Integration recipe + CRM contact"},{"id":"mcp_agents_run_approve","label":"List fleet and pending approvals"},{"id":"mcp_agents_fleet_orient","label":"Read agent templates, fleet, and automation map"},{"id":"mcp_agents_create_from_template","label":"Create an agent from a catalog template"},{"id":"mcp_knowledge_ingest","label":"Knowledge config + KB ingest + health"},{"id":"mcp_knowledge_answer_tune","label":"Knowledge prompt tune → playground → promote"},{"id":"mcp_knowledge_acceptance_promote","label":"Knowledge acceptance suite → promote"},{"id":"mcp_crm_contact_deal","label":"CRM contact upsert + deal pipeline"},{"id":"mcp_hosted_vertical_bootstrap","label":"Hosted vertical workspace bootstrap"},{"id":"mcp_support_inbox","label":"Support staff inbox queue"},{"id":"mcp_support_respond_v1","label":"Support staff respond (inbox → reply)"},{"id":"mcp_analyst_readonly_v1","label":"Analyst read-only (RAG + CRM)"},{"id":"mcp_integration_ops_v1","label":"Integration ops (recipes + scheduler probe)"},{"id":"mcp_integrations_universal_connect_v1","label":"Universal connect (schema + install + test_hook)"},{"id":"mcp_content_writer_v1","label":"Content writer (hosting + RAG read)"},{"id":"mcp_business_composite_v1","label":"Business composite (snapshot + Compass setup)"},{"id":"mcp_tenant_business_assistant_v1","label":"Tenant business assistant (head + operator + Telegram)"},{"id":"mcp_bots_simulate","label":"Bots list + simulate (heavy LLM)"},{"id":"mcp_generation_diff","label":"Generation diff vs prod + gates"},{"id":"mcp_universal_safe_change","label":"Universal safe tenant change (preflight → promote)"},{"id":"mcp_bot_ai_release","label":"Bot AI release (logic only, no channel)"},{"id":"mcp_hosting_edit_site_safe","label":"Edit hosted site safely"},{"id":"mcp_hosting_edit_text_file_v1","label":"Edit one hosted text file (one patch, gzip refreshed)"},{"id":"mcp_hosting_static_landing_v1","label":"Publish static HTML landing (/s/)"},{"id":"mcp_site_growth_v1","label":"Site growth ladder (profile, site, quota, config)"},{"id":"mcp_notify_channels_v1","label":"Notification channels (bots, prefs, inbox)"},{"id":"mcp_platform_flows_v1","label":"Platform flows (preflight, sandbox, recipe atlas)"},{"id":"mcp_hosting_react_dist_v1","label":"Deploy pre-built React/Vite dist"},{"id":"mcp_project_data_safe_patch","label":"Safe 8DNA leaf patch"},{"id":"mcp_user_access_safe","label":"Safe user access + FAP"},{"id":"mcp_project_operator_session","label":"Project orchestrator operator session"},{"id":"mcp_orchestrator_memory_bootstrap","label":"Orchestrator RAG + memory bootstrap"},{"id":"mcp_agent_knowledge_memory_setup","label":"Agent knowledge + episodic memory setup"},{"id":"mcp_project_faq_bootstrap","label":"FAQ persona orchestrator bootstrap"},{"id":"mcp_readonly_audit_v1","label":"Read-only MCP certification audit"},{"id":"mcp_agent_certification_v1","label":"Agent mutation certification with verify"},{"id":"mcp_ecosystem_cert_wave_a_v1","label":"Ecosystem cert Wave A (inventory & contract)"},{"id":"mcp_ecosystem_cert_wave_b_v1","label":"Ecosystem cert Wave B (sandbox CRUD)"},{"id":"mcp_ecosystem_cert_wave_c_v1","label":"Ecosystem cert Wave C (deep lifecycles)"},{"id":"mcp_ecosystem_cert_wave_d_v1","label":"Ecosystem cert Wave D (golden E2E paths)"},{"id":"mcp_ecosystem_cert_wave_e_v1","label":"Ecosystem cert Wave E (security probes)"},{"id":"mcp_ecosystem_cert_wave_g_v1","label":"Ecosystem cert Wave G (certificate rollup)"}],"recipes_extended":[{"name":"Compass playbook match","description":"Canonical PlaybookIds: guidance.list. NL goal → playbook via goal_text (aliases goal/query/intent coerced); match returns catalog_entry + verifyKinds from enriched compass_playbooks_intents_v1.json (51/51). Then guidance.start_path. PTC catalog: guidance.list_capability_tasks.","tools":["guidance.list","guidance.match_playbook","guidance.list_capability_tasks","guidance.start_path"],"recipe_id":"mcp_guidance_match"},{"name":"Build a React app on the platform","description":"mcp_app_studio_v1 does not run. One phase per batch: edit is source.patch, build is enqueue then status, publish only when asked. A replacements string is literal, including JSX braces. Editing /s/ bytes is hosting.bucket.file.patch.","tools":["ai_builder.source.patch"],"recipe_id":"mcp_app_studio_v1"},{"name":"Create an App Studio tree","description":"Template phase. compose.apply with blueprint_id and branch. Skip when the tree already exists.","tools":["ai_builder.compose.apply"],"recipe_id":"mcp_app_studio_create_v1"},{"name":"Edit an App Studio slot","description":"Known string: one source.patch replacements. Whole function: symbols [{name, replace}]. view=skeleton only to learn the name. Pass expected_sha256; a mismatch writes nothing. agent_completion.done starts the build batch.","tools":["ai_builder.source.get","ai_builder.source.patch"],"recipe_id":"mcp_app_studio_edit_v1"},{"name":"Build an App Studio tree","description":"enqueue then status. Omit build_uuid. On failed: read errors[0].file and line, patch that src file (not package.json), enqueue again. Does not publish.","tools":["ai_builder.build.enqueue","ai_builder.build.status"],"recipe_id":"mcp_app_studio_build_v1"},{"name":"Publish an App Studio build","description":"Only when the user asks to publish. Omit bucket_id when a primary site exists.","tools":["ai_builder.publish"],"recipe_id":"mcp_app_studio_publish_v1"},{"name":"Knowledge mentor playground","description":"One heavy playground turn (mentor simulate with RAG trace)","tools":["knowledge.playground"],"recipe_id":"mcp_knowledge_playground"},{"name":"Key2Unity auth portal supply","description":"Bucket resolve, persona leaves, bot identity, generation promote — not vertical_workspace.bootstrap","tools":["hosting.site.resolve","projects.patch_data","bots.update","generation.diff_vs_prod","generation.promote"],"recipe_id":"mcp_key2unity_auth_portal"},{"name":"Grant OS pipeline ops","description":"Hub snapshot, opportunity upsert, packet sync, compose, bundle","tools":["grants.crm.hub_snapshot","grants.opportunity.upsert","grants.crm.sync","grants.compose.checklist","grants.bundle.download"],"recipe_id":"mcp_grants_os_crm_ops"},{"name":"Studio diagnostic SoW","description":"Render kickoff SoW from catalog + optional CRM persist","tools":["services.diagnostic_sow_draft"],"recipe_id":"mcp_studio_diagnostic_sow"},{"name":"Studio phase-1 knowledge mentor","description":"Delivery slot, hosting, RAG, bot, promote","tools":["services.apply_delivery_slot","hosting.site.quick_start","rag.collection_create","bots.create","generation.promote"],"recipe_id":"mcp_studio_phase1_knowledge_mentor"},{"name":"Webhook + scheduler iPaaS","description":"Inbound webhook recipe + scheduled task","tools":["integrations.list_recipes","integrations.install_recipe","scheduler.create_task"],"recipe_id":"mcp_integrations_webhook_scheduler"},{"name":"CRM lead + notify","description":"Lead capture recipe + staff notification","tools":["integrations.install_recipe","integrations.connection_health","notifications.send_push"],"recipe_id":"mcp_integrations_crm_lead_notify"},{"name":"Studio phase-1 data migration","description":"Migrator cutover: discovery, tenant, DNA leaf, gates, promote","tools":["services.apply_delivery_slot","discovery.list","auth.get_profile","projects.create_project","projects.patch_data","storage.get_quota","logic.create","scheduler.create_task","generation.diff_vs_prod","generation.gates","generation.promote"],"recipe_id":"mcp_studio_phase1_data_migration"},{"name":"Agents fleet orientation (binding + diagnostics)","description":"Fleet diagnostics, binding reconcile when stale, then template catalog.","tools":["agents.fleet_diagnostics","agents.reconcile_binding","agents.templates_list","agents.list"],"recipe_id":"mcp_agents_fleet_orientation_v1"},{"name":"Inspect one agent","description":"Spec, policy preview, and automation map for one agent.","tools":["agents.get","agents.policy_preview","agents.automation_map"],"recipe_id":"mcp_agents_inspect"},{"name":"Merge one agent section","description":"Deep-merge one AgentSpec section via update_agent_spec. Lists replace; objects merge.","tools":["agents.update"],"recipe_id":"mcp_agents_patch_section"},{"name":"Mark agent ready","description":"Set lifecycle state to ready so triggers can fire. Does not set live.","tools":["agents.update"],"recipe_id":"mcp_agents_set_ready"},{"name":"Bind RAG collections to an agent","description":"Confirm a collection, then merge rag_settings.collection_ids. Does not create the collection.","tools":["rag.collection_get","agents.update"],"recipe_id":"mcp_agents_bind_rag"},{"name":"Schedule an agent","description":"Merge scheduler.tick plus a preset. Do not add chat triggers if support or a bot already owns the agent.","tools":["agents.update"],"recipe_id":"mcp_agents_schedule"},{"name":"Import agent from asset","description":"Load an asset, then fulfill it. The asset object is passed as recipe_params.asset from assets.get.","tools":["assets.get"],"recipe_id":"mcp_agents_import_asset"},{"name":"Fulfill agent asset","description":"Create an agent from a commerce asset object returned by assets.get.","tools":["agents.import_from_asset"],"recipe_id":"mcp_agents_import_apply"},{"name":"Fork an agent generation","description":"DNA child generation of one agent. This is not generation.fork.","tools":["agents.fork"],"recipe_id":"mcp_agents_fork"},{"name":"Enqueue an agent run","description":"Queue one run with wait false. Poll is a separate recipe.","tools":["agents.run"],"recipe_id":"mcp_agents_run_enqueue"},{"name":"Poll an agent run","description":"Read run status. run_id is the previous run_uuid.","tools":["agents.run_get"],"recipe_id":"mcp_agents_run_poll"},{"name":"Debug an agent run","description":"Status, traces, and recent timeline for one agent.","tools":["agents.run_get","agents.traces","agents.timeline"],"recipe_id":"mcp_agents_debug"},{"name":"Approve a waiting run","description":"List pending approvals, then approve one run. Not part of create.","tools":["agents.list_pending_approvals","agents.approve_run"],"recipe_id":"mcp_agents_approve_run"},{"name":"Stop an agent run","description":"Cancel one queued or running run.","tools":["agents.stop"],"recipe_id":"mcp_agents_stop"},{"name":"Kill an agent","description":"Set lifecycle to killed so new runs stop. Not for a single stuck run — use mcp_agents_stop.","tools":["agents.kill"],"recipe_id":"mcp_agents_kill"},{"name":"Configure project orchestrator","description":"Read and patch project orchestrator config. Does not call agents.orchestrate.","tools":["projects.orchestrator.get","projects.orchestrator.patch"],"recipe_id":"mcp_agents_orchestrator_configure"},{"name":"Run project orchestrator once","description":"One agents.orchestrate call with wait false. Poll the returned run_uuid as run_id.","tools":["agents.orchestrate"],"recipe_id":"mcp_agents_orchestrate_once"},{"name":"Enqueue a handoff run","description":"Parent run carries handoff_to_agent_id. The child starts only after the parent completes.","tools":["agents.run"],"recipe_id":"mcp_agents_handoff_enqueue"},{"name":"Review agent sandbox diff","description":"Diff and gates for an existing sandbox anchor. Not in the same batch as agents.update.","tools":["generation.diff_vs_prod","generation.gates"],"recipe_id":"mcp_agents_generation_review"},{"name":"Promote an agent version","description":"Agent version gates and agents.promote. Not generation.promote.","tools":["agents.metrics","agents.gates","agents.promote"],"recipe_id":"mcp_agents_version_promote"},{"name":"Bind agent as bot brain","description":"Set bot brain.mode=agent and brain.agent_uuid. Merge keeps other brain fields. No simulate in this batch.","tools":["bots.get","bots.update"],"recipe_id":"mcp_agents_bind_bot_brain"},{"name":"Bind agent to support config","description":"Set support config ai_agent_uuid and ai_mode, then read binding health. Does not add chat triggers or a bot brain.","tools":["social.support.config.patch","social.support.ai_binding_health"],"recipe_id":"mcp_agents_bind_support"},{"name":"Implementer then browser verifier","description":"Enqueue orchestrator implementer run, poll status, then enqueue verifier template with writes_allowed=false (browser_verification evidence on parent).","tools":["agents.orchestrate","agents.run_get","agents.create","agents.run_get"],"recipe_id":"mcp_agents_implementer_verifier_v1"},{"name":"Corporate mailbox read","description":"List @agentstack.tech mailbox threads then open one thread.","tools":["messaging.inbox.list","messaging.inbox.get"],"recipe_id":"mcp_messaging_mailbox_v1"},{"name":"Upload to project storage","description":"Check quota then load the REST upload contract.","tools":["storage.get_quota","storage.upload"],"recipe_id":"mcp_storage_upload"},{"name":"Manage stored files","description":"List project files and re-check quota.","tools":["storage.list_files","storage.get_quota"],"recipe_id":"mcp_storage_manage"},{"name":"Knowledge base search","description":"Health check then semantic search across project knowledge.","tools":["knowledge.health","rag.search"],"recipe_id":"mcp_knowledge_search"},{"name":"Promote sandbox generation","description":"Diff sandbox vs prod then promote when gates pass.","tools":["generation.diff_vs_prod","generation.promote"],"recipe_id":"mcp_generation_promote"},{"name":"Commerce orientation","description":"Read balance, wallets, and assets before any charge or deposit.","tools":["payments.get_balance","wallets.list","assets.list"],"recipe_id":"mcp_commerce_orient"},{"name":"Open a wallet","description":"Create one wallet. Deposit is the next recipe after you copy wallet_id.","tools":["wallets.create"],"recipe_id":"mcp_commerce_wallet_open"},{"name":"Deposit to a wallet","description":"Credit a wallet you already listed. Do not invent wallet_id from the same batch.","tools":["wallets.deposit"],"recipe_id":"mcp_commerce_wallet_deposit"},{"name":"Treasury and wallets","description":"Project treasury portfolio beside personal or commerce wallets.","tools":["finance.project.portfolio","wallets.list"],"recipe_id":"mcp_treasury_read"},{"name":"Logic rules orientation","description":"List rules and processors before creating another rule.","tools":["logic.list","logic.get_processors"],"recipe_id":"mcp_logic_orient"},{"name":"Create a logic rule","description":"Create one rule from recipe_params. Dry-run that id in the next recipe.","tools":["logic.create"],"recipe_id":"mcp_logic_create"},{"name":"Dry-run a logic rule","description":"Simulate an existing rule. logic.dry_run needs logic_id, not a spec.","tools":["logic.dry_run"],"recipe_id":"mcp_logic_dry_run"},{"name":"Scheduled tasks","description":"List cron tasks. Create is a separate recipe.","tools":["scheduler.list_tasks"],"recipe_id":"mcp_scheduler_orient"},{"name":"Create a scheduled task","description":"One scheduler.create_task. Required shape is name, cron, and command. timezone defaults to UTC. execute_at is a single run; cron without it stays recurring.","tools":["scheduler.create_task"],"recipe_id":"mcp_scheduler_task"},{"name":"Storage quota and files","description":"Quota and the root folder. Upload bytes stay on REST.","tools":["storage.get_quota","storage.list_files"],"recipe_id":"mcp_storage_orient"},{"name":"Match a Compass playbook","description":"Map a goal sentence to a playbook id. Start that path in the next recipe.","tools":["guidance.list","guidance.match_playbook"],"recipe_id":"mcp_guidance_match"},{"name":"Start a Compass path","description":"Start a known playbook and read path status.","tools":["guidance.start_path","guidance.path_status"],"recipe_id":"mcp_guidance_start"},{"name":"Search a knowledge collection","description":"One rag.search. Ingest and playground stay in the knowledge recipes.","tools":["rag.search"],"recipe_id":"mcp_rag_search"},{"name":"List messenger channels","description":"Discover channels. History is the next recipe once you have channel_id.","tools":["social.channels.list"],"recipe_id":"mcp_messenger_channels"},{"name":"Read a messenger channel","description":"Read one channel. Posting is social.chat.post in a later batch.","tools":["social.chat.history"],"recipe_id":"mcp_messenger_history"},{"name":"Business organism read","description":"Org summary and command snapshot for a head project.","tools":["business.get_org","business.command_snapshot"],"recipe_id":"mcp_business_read"},{"name":"Create a business composite","description":"One business.create_composite. Organs are a list you pass in.","tools":["business.create_composite"],"recipe_id":"mcp_business_composite"},{"name":"Create a scoped API key","description":"Mint one agent PAT. The secret is returned once.","tools":["apikeys.create"],"recipe_id":"mcp_apikey_scoped"},{"name":"Effective buff limits","description":"Read effective limits before creating or applying a buff template.","tools":["buffs.get_effective_limits"],"recipe_id":"mcp_buffs_orient"},{"name":"Create a buff template","description":"Create a PENDING buff template. For subscription/SKU entitlements use grant rails (grant_tenant_subscription / grant_subscription / mcp_tenant_subscription_monetization) — not mcp_buffs_apply. mcp_buffs_apply is for non-subscription templates (promo, event, limits).","tools":["buffs.create_buff"],"recipe_id":"mcp_buffs_create"},{"name":"Apply a buff","description":"Activate a PENDING buff on a user or project. buff_id comes from create, not from this batch. Platform tiers: buffs.grant_subscription (PID=1). Tenant manual: buffs.grant_tenant_subscription. Tenant paid checkout: webhook/C24 auto-grant — not this recipe after payments.create.","tools":["buffs.apply_buff"],"recipe_id":"mcp_buffs_apply"},{"name":"Apply field-access defaults","description":"Copy missing FAP resources onto a user project. Does not target ecosystem project 1.","tools":["data_access.apply_defaults_template"],"recipe_id":"mcp_fap_defaults"},{"name":"Send one notice","description":"Deliver one notice after mcp_notify_channels_v1. The recipient must already be enrolled on a bot channel.","tools":["notifications.deliver"],"recipe_id":"mcp_notify_deliver"},{"name":"Plan a storefront seed","description":"Dry-run a catalog pack. Apply is the next recipe and needs the plan object.","tools":["commerce.storefront.seed_plan"],"recipe_id":"mcp_storefront_plan"},{"name":"Apply a storefront seed","description":"Write the plan returned by commerce.storefront.seed_plan.","tools":["commerce.storefront.seed_apply"],"recipe_id":"mcp_storefront_apply"},{"name":"Safety text probe","description":"Evaluate one text. Config patch and promote stay in later batches.","tools":["safety.evaluate"],"recipe_id":"mcp_safety_probe"},{"name":"List hosted bucket files","description":"List files on the primary site or a named bucket. This is the /s/ tree, not storage.","tools":["hosting.bucket.files.list"],"recipe_id":"mcp_site_file_list"},{"name":"Read one hosted text file","description":"Read one UTF-8 bucket file when the bytes are unknown. A known string is mcp_hosting_edit_text_file_v1 and does not need this digest.","tools":["hosting.bucket.file.get"],"recipe_id":"mcp_site_file_read"},{"name":"Snapshot a hosted bucket","description":"Immutable copy before a text write. The orchestrator allows this on mcp or workspace when competence_tier is dev_operator.","tools":["hosting.release.snapshot"],"recipe_id":"mcp_site_file_snapshot"},{"name":"Search-replace a hosted text file","description":"Prefer mcp_hosting_edit_text_file_v1: one search_replace, no GET and no dry_run. This recipe previews then applies only when expected_sha256 is already in hand.","tools":["hosting.bucket.file.patch","hosting.bucket.file.patch"],"recipe_id":"mcp_site_file_replace"},{"name":"Replace a hosted text file","description":"Whole-file replace when the new body is already known. A substring edit is mcp_hosting_edit_text_file_v1. agent_completion.done means skip edge_health.","tools":["hosting.bucket.file.patch","hosting.bucket.file.patch"],"recipe_id":"mcp_site_file_write"},{"name":"Check hosted edge","description":"After hosting.deploy_files, until edge_ready. A file.patch result with agent_completion.done does not need this read.","tools":["hosting.site.edge_health"],"recipe_id":"mcp_site_edge"},{"name":"List user or project files","description":"List attachment files for the signed-in user or the project folder. Not the hosted /s/ tree.","tools":["storage.list_files"],"recipe_id":"mcp_storage_scope"},{"name":"Storage upload contract","description":"Return the REST multipart contract. MCP does not carry file bytes. A user avatar is POST /api/profile/avatar, not this recipe.","tools":["storage.upload"],"recipe_id":"mcp_storage_upload_gate"},{"name":"Delete one stored file","description":"Delete one registry file. file_id comes from a previous list.","tools":["storage.delete_file"],"recipe_id":"mcp_storage_delete"},{"name":"FAQ reply desk","description":"Bot and messenger answer from docs. Rebinds every bot brain. Does not bind support.","tools":["projects.orchestrator.patch"],"recipe_id":"mcp_orch_faq_desk"},{"name":"Support reply desk","description":"Messenger support replies. Does not rebind bot brains.","tools":["projects.orchestrator.patch"],"recipe_id":"mcp_orch_support_desk"},{"name":"API reply desk","description":"External system calls the orchestrator run REST path with channel api. Key is mcp_apikey_scoped.","tools":["projects.orchestrator.patch"],"recipe_id":"mcp_orch_api_desk"},{"name":"Dev operator desk","description":"mcp and workspace may snapshot and patch site text. Reply sync flags stay as they are.","tools":["projects.orchestrator.patch"],"recipe_id":"mcp_orch_dev_desk"},{"name":"Business operator desk","description":"Tenant business assistant: dev_operator on bot/mcp, no mass bot_brain_sync.","tools":["projects.orchestrator.patch"],"recipe_id":"mcp_orch_business_operator_desk"},{"name":"Docs memory desk","description":"Point orchestrator memory at collection ids copied from a prior search or ingest.","tools":["projects.orchestrator.patch"],"recipe_id":"mcp_orch_docs_desk"},{"name":"Elevate operator capabilities","description":"Replace policy.capabilities with the elevated list, including file delete and role change.","tools":["agents.update"],"recipe_id":"mcp_orch_operator_caps"},{"name":"List project users","description":"Read project members. Role change is the next recipe.","tools":["projects.get_users"],"recipe_id":"mcp_users_list"},{"name":"Change a project role","description":"Set a member role. user_id comes from mcp_users_list. Owner cannot be assigned here.","tools":["projects.update_user_role"],"recipe_id":"mcp_users_role"}],"discovery_ladder":[{"step":0,"label":"Session probe","url":"/mcp/prompts/get?name=agentstack_session_setup","method":"GET","action":"auth.get_profile"},{"step":1,"label":"Work Graph default (bound project)","url":"agents.work_next","method":"MCP","action":"agents.work_next","skill":"/mcp/prompts/get?name=agentstack_work_graph"},{"step":2,"label":"Registry status","url":"discovery.status","method":"MCP"},{"step":3,"label":"Schema lookup only — prefer packet.next_action","url":"discovery.search","method":"MCP"},{"step":4,"label":"Describe chosen action","url":"discovery.describe","method":"MCP"},{"step":5,"label":"Preflight then execute","url":"preflight.check","method":"MCP"}],"machine_discovery_ladder":[{"step":0,"label":"Session probe","url":"/mcp/prompts/get?name=agentstack_session_setup","method":"GET","action":"auth.get_profile"},{"step":1,"label":"Work Graph default (bound project)","url":"agents.work_next","method":"MCP","action":"agents.work_next","skill":"/mcp/prompts/get?name=agentstack_work_graph"},{"step":2,"label":"Registry status","url":"discovery.status","method":"MCP"},{"step":3,"label":"Schema lookup only — prefer packet.next_action","url":"discovery.search","method":"MCP"},{"step":4,"label":"Describe chosen action","url":"discovery.describe","method":"MCP"},{"step":5,"label":"Preflight then execute","url":"preflight.check","method":"MCP"}],"http_bootstrap_ladder":[{"step":0,"label":"Contract (slim)","url":"/mcp/ai_prompt?mode=contract","method":"GET"},{"step":1,"label":"Server manifest","url":"/mcp/manifest","method":"GET"},{"step":2,"label":"Organs map","url":"/mcp/organs","method":"GET"},{"step":3,"label":"Public catalog schemas","url":"/mcp/actions?schemas=public","method":"GET"}],"closed_loop_ladder":[{"step":0,"step_id":"session","label":"Session + project","detail":"/mcp/prompts/get?name=agentstack_session_setup — bind context.project_id"},{"step":1,"step_id":"route","label":"Route goal","detail":"Cold start: no project_id → agentstack_session_setup only. Do not discovery.search until context.project_id is set. Bound project: agents.work_next first; discovery.search only when packet.next_action is absent. Status-only poll → agents.work_status (no claim params)."},{"step":2,"step_id":"plan_read","label":"Plan read + sandbox","detail":"agents.plan_get — include_execution_eligibility=true; optional env_uuid for sandbox slice"},{"step":3,"step_id":"work_pick","label":"Pick next work","detail":"agents.work_next — read dependency_ready (structural) vs execution_ready (fleet) separately; blocked_work.execution_summary + instruction_packet.execution_summary; dependency_ready=false → wait deps; execution_ready=false with deps ok → provision before claim"},{"step":4,"step_id":"plan_draft","label":"Draft / decompose (optional)","detail":"agents.plan_propose → validation.plan_valid + execution.execution_summary → agents.plan_apply_proposal (same env_uuid and validation_mode); persist_unexecutable for intake-only (H8); plan_process_backlog auto_apply=off; facet_repair bounded max 2 (H9); planning_artifact evidence-only (H10)"},{"step":5,"step_id":"claim_execute","label":"Claim + execute","detail":"agents.plan_claim — CAS revision; role_mismatch → handoff not retry loop → agents.plan_execute — only after claim; attach evidence for completion_predicates; ensure_agent create=false then create=true when provision_required (H5/H7)"},{"step":6,"step_id":"verify_recover","label":"Verify + recover","detail":"completion not_evaluable ≠ passed; verification_failed → agents.plan_recovery_scan — verification_failed candidates + stale claims; optional env_uuid; agents.plan_propose mode=repair_plan — target node_id; allow_generic_acceptance repair-only; agents.plan_apply_proposal — same env_uuid as propose on sandbox forks; agents.work_next handoff=true node_id=… — re-resolve after repair or provision; diagnostics reconcile"},{"step":7,"step_id":"business_team","label":"Business / team (optional)","detail":"/mcp/prompts/get?name=agentstack_business_organism for head+organs; agents.team.create + templates for specialist fleet"}],"inverse_orchestration_ladder":[{"step":0,"label":"Resume workflow_run_id","detail":"Pass the same workflow_run_id from the prior execute response when continuing a playbook."},{"step":1,"label":"Read instruction_packet","detail":"Use only allowed_actions from the last packet; respect writes_allowed and forbidden_actions."},{"step":2,"label":"Execute one allowed action","detail":"agentstack.execute with a single tool from allowed_actions; do not batch unrelated writes."},{"step":3,"label":"On violation","detail":"orchestration_step_violation means the tool was outside the current step — re-read discovery.describe, do not retry blindly."},{"step":4,"label":"Async handoff","detail":"options.async=true returns job_id — poll discovery.job_status or MCP tasks/get (same receipt; tasks/result when completed). One semantic, two client APIs."}],"execute_pipeline":[{"id":"gpt_body","phase":"ingress","fn":"_normalize_gpt_actions_body"},{"id":"recipe","phase":"ingress","fn":"_expand_recipe_steps"},{"id":"validate_steps","phase":"ingress","fn":"_validate_steps"},{"id":"sync_budget","phase":"ingress","fn":"prepare_sync_execute"},{"id":"resolve_context","phase":"auth","fn":"resolve_mcp_context"},{"id":"body_context","phase":"auth","fn":"coalesce_execute_body_context"},{"id":"context_override_gate","phase":"auth","fn":"_validate_execute_context_overrides"},{"id":"resolve_tool","phase":"step","fn":"_resolve_tool_name"},{"id":"normalize_params","phase":"step","fn":"normalize_params"},{"id":"coerce","phase":"step","fn":"apply_tool_coercions"},{"id":"validate_params","phase":"step","fn":"validate_tool_params"},{"id":"service_caps","phase":"step","fn":"L1_service_caps"},{"id":"fabric_guard","phase":"step","fn":"run_fabric_guard"},{"id":"generation_fork","phase":"step","fn":"try_auto_fork_before_mcp_tool"},{"id":"handler","phase":"step","fn":"MCP_TOOLS_REGISTRY"},{"id":"post_process","phase":"step","fn":"post_process_mcp_tool_result"}],"flow_receipt_schema":{"flow_id":"str","project_id":"int","env_uuid":"str|null","catalog_etag":"str","trace_ids":["str"],"tests":{"passed":"int","failed":"int"},"gates":["object"],"recovery":{"checkpoint_id":"str|null"},"final_state":"completed|blocked|aborted|rolled_back"},"flow_catalog":{"recipe_to_flow":{"mcp_generation_diff":"UF_DIAGNOSE","mcp_knowledge_ingest":"UF_KNOWLEDGE_READ","mcp_knowledge_answer_tune":"UF_KNOWLEDGE_PROMPT_TUNE","mcp_knowledge_acceptance_promote":"UF_KNOWLEDGE_VALIDATE","mcp_universal_safe_change":"UF_F1_ROUTINE","mcp_bot_ai_release":"UF_F1_ROUTINE","mcp_project_data_safe_patch":"UF_F1_ROUTINE","mcp_user_access_safe":"UF_F1_ROUTINE","mcp_tenant_bots_heal_verify":"UF_BOTS_HEAL","mcp_tenant_business_assistant_v1":"UF_TENANT_BUSINESS_ASSISTANT","mcp_hosted_vertical_bootstrap":"UF_HOSTED_BOOTSTRAP","mcp_key2unity_auth_portal":"UF_KEY2UNITY_PORTAL","mcp_site_growth_v1":"UF_SITE_GROWTH","mcp_read_bootstrap":"UF_SITE_GROWTH","mcp_hosting_quickstart":"UF_SITE_GROWTH","mcp_hosting_static_landing_v1":"UF_SITE_GROWTH","mcp_hosting_edit_site_safe":"UF_SITE_GROWTH","mcp_hosting_edit_text_file_v1":"UF_SITE_GROWTH","mcp_hosting_react_dist_v1":"UF_SITE_GROWTH","mcp_showcase_catalog_safe":"UF_SHOWCASE_CATALOG","mcp_agents_fleet_orient":"UF_AGENTS_CONFIGURE","mcp_agents_create_from_template":"UF_AGENTS_CONFIGURE","mcp_agents_patch_section":"UF_AGENTS_CONFIGURE","mcp_agents_set_ready":"UF_AGENTS_CONFIGURE","mcp_agents_bind_rag":"UF_AGENTS_CONFIGURE","mcp_agents_bind_support":"UF_AGENTS_CONFIGURE","mcp_agents_bind_bot_brain":"UF_AGENTS_CONFIGURE","mcp_agents_schedule":"UF_AGENTS_CONFIGURE","mcp_agents_run_enqueue":"UF_AGENTS_RUN","mcp_agents_handoff_enqueue":"UF_AGENTS_RUN","mcp_agents_orchestrate_once":"UF_AGENTS_RUN","mcp_work_loop_v1":"UF_WORK_GRAPH_LOOP","mcp_integrations_checkout_crm":"UF_F1_ROUTINE","mcp_integrations_universal_connect_v1":"UF_F1_ROUTINE","mcp_integration_ops_v1":"UF_DIAGNOSE","mcp_crm_contact_deal":"UF_F1_ROUTINE","mcp_stackscript_promote_v1":"UF_STACKSCRIPT_PROMOTE","mcp_stackscript_sandbox_v1":"UF_STACKSCRIPT_SANDBOX","mcp_agents_run_approve":"UF_AGENTS_RUN","mcp_support_inbox":"UF_DIAGNOSE","mcp_support_respond_v1":"UF_AGENTS_RUN","mcp_analyst_readonly_v1":"UF_KNOWLEDGE_READ","mcp_content_writer_v1":"UF_SITE_GROWTH","mcp_business_composite_v1":"UF_SUPPLY_READ","mcp_bots_simulate":"UF_BOTS_HEAL","mcp_notify_channels_v1":"UF_SUPPLY_READ","mcp_platform_flows_v1":"UF_SUPPLY_READ","mcp_agent_knowledge_memory_setup":"UF_KNOWLEDGE_READ"},"flows":{"UF_SUPPLY_READ":{"flow_id":"UF_SUPPLY_READ","title":"Supply plane snapshot","intent":"Confirm buff, quota, auto_generation settings before any mutation.","matrix_ref":"F9","prod_safe":true,"steps":[{"step_id":"supply","action":"generation.supply_status","mutates":false,"env_pin":"none"},{"step_id":"settings","action":"generation.settings.get","mutates":false,"env_pin":"none"},{"step_id":"list","action":"generation.list","mutates":false,"env_pin":"none"},{"step_id":"status","action":"generation.status","mutates":false,"env_pin":"none"}]},"UF_F1_ROUTINE":{"flow_id":"UF_F1_ROUTINE","title":"Routine tenant edit → promote","intent":"Fork or auto-fork → patch → diff → gates → promote.","matrix_ref":"F1","prod_safe":false,"steps":[{"step_id":"fork","action":"generation.fork","mutates":true,"env_pin":"none"},{"step_id":"patch","action":"knowledge.config.patch","mutates":true,"env_pin":"required"},{"step_id":"diff","action":"generation.diff_vs_prod","mutates":false,"env_pin":"required"},{"step_id":"gates","action":"generation.gates","mutates":false,"env_pin":"required"},{"step_id":"promote","action":"generation.promote","mutates":true,"env_pin":"required"}]},"UF_DIAGNOSE":{"flow_id":"UF_DIAGNOSE","title":"Diagnose pending sandbox","intent":"List open envs, diff vs prod, timeline — never promote.","matrix_ref":"F2","prod_safe":true,"steps":[{"step_id":"list","action":"generation.list","mutates":false,"env_pin":"none"},{"step_id":"diff","action":"generation.diff_vs_prod","mutates":false,"env_pin":"required"},{"step_id":"timeline","action":"generation.timeline","mutates":false,"env_pin":"none"}]},"UF_KNOWLEDGE_READ":{"flow_id":"UF_KNOWLEDGE_READ","title":"Knowledge plane read","intent":"Config + health before ingest or playground.","matrix_ref":"F2","prod_safe":true,"steps":[{"step_id":"cfg","action":"knowledge.config.get","mutates":false,"env_pin":"none"},{"step_id":"health","action":"knowledge.health","mutates":false,"env_pin":"none"}]},"UF_KNOWLEDGE_VALIDATE":{"flow_id":"UF_KNOWLEDGE_VALIDATE","title":"Patch + playground validate","intent":"Sandbox patch → diff → playground (heavy) with generation_env_uuid context.","matrix_ref":"F1","prod_safe":false,"steps":[{"step_id":"patch","action":"knowledge.config.patch","mutates":true,"env_pin":"required"},{"step_id":"diff","action":"generation.diff_vs_prod","mutates":false,"env_pin":"required"},{"step_id":"playground","action":"knowledge.playground","mutates":false,"env_pin":"optional"}]},"UF_BOTS_HEAL":{"flow_id":"UF_BOTS_HEAL","title":"Mentor bots heal → promote","intent":"ensure_mentor_commands per bot → diff → gates → promote (repeat heal per bot_id).","matrix_ref":"F1","prod_safe":false,"steps":[{"step_id":"heal","action":"bots.ensure_mentor_commands","mutates":true,"env_pin":"none"},{"step_id":"diff","action":"generation.diff_vs_prod","mutates":false,"env_pin":"required"},{"step_id":"gates","action":"generation.gates","mutates":false,"env_pin":"required"},{"step_id":"promote","action":"generation.promote","mutates":true,"env_pin":"required"}]}}},"discovery":{"catalog_actions_public":752,"catalog_domains_public":59,"actions_summary_url":"/mcp/actions/summary","ai_prompt_url":"/mcp/ai_prompt","manifest_url":"/mcp/manifest","organs_url":"/mcp/organs","discovery_url":"/mcp/discovery","actions_url":"/mcp/actions","health_url":"/mcp/health","prompts_url":"/mcp/prompts/get","intent_url":"/mcp/discover/by_intent","recipes_url":"/mcp/recipes","oauth_connect_help_url":"/mcp/connect","oauth_authorize_well_known_url":"/.well-known/oauth-authorization-server/mcp","oauth_protected_resource_well_known_url":"/.well-known/oauth-protected-resource/mcp","oauth_authorize_path":"/mcp/.well-known/oauth-authorize","oauth_token_path":"/mcp/.well-known/oauth-token","oauth_browser_bridge_path":"/api/auth/mcp-oauth-bridge"},"catalog":{"total_actions":null,"domains":null},"context_hint":"OAuth / Device Code keys often bind to ecosystem project_id=1. Set context.project_id to the tenant project before logic.* and session-scoped reads.","stale_action_policy":"Prefer GET /mcp/actions over docs; auth.login not auth.quick_auth; apikeys.* not legacy projects API-key aliases; logic.* not rules.*; scheduler.create_task not schedule_task; notifications.send_push for OS push; notifications.deliver for email and bot channels; not notifications.send.","clients":[],"product_archetypes":[{"id":"game","name":"Game Development","signals":["player_management","game_mechanics","monetization","engagement"],"prompt":"agentstack_use_case_game","recipe_ids":["card_game_basic","rpg_character_system","casual_game_monetization"],"mcp_recipe_id":"card_game_basic","flow_id":null,"sdk_hint":null,"showcase_key":null,"deep_link":"prompt `agentstack_use_case_game` · recipe `card_game_basic`","minimum_domains":["projects"],"optional_domains":[],"do_not_add_unless_asked":["crm.upsert_contact","hosting.site.quick_start"]},{"id":"saas","name":"SaaS Platform","signals":["trials","subscriptions","usage_limits","feature_flags"],"prompt":"agentstack_use_case_saas","recipe_ids":["saas_trial_system","mcp_platform_subscription_grant","mcp_tenant_subscription_monetization","mcp_tenant_manual_entitlement_grant"],"mcp_recipe_id":"saas_trial_system","flow_id":"create_project_value","sdk_hint":"sdk.platform.auth","showcase_key":"course-academy","deep_link":"`/agentstack-scaffold-auth` → `/agentstack-scaffold-backend`","minimum_domains":["projects","auth","ai_builder"],"optional_domains":["crm","logic","payments","hosting"],"do_not_add_unless_asked":["business.create_composite","rag.document_add","agents.create"],"recommended_playbook":"saas_build_v1","success_criteria":["build_ok","primary_public_url","edge_ready"]},{"id":"ecommerce","name":"E-Commerce","signals":["product_catalog","cart_checkout","inventory","promotions"],"prompt":"agentstack_use_case_ecommerce","recipe_ids":["online_store_basic","marketplace_platform"],"mcp_recipe_id":"mcp_hosting_quickstart","flow_id":"host_then_sell","sdk_hint":"sdk.commerce","showcase_key":"collectibles-bazaar","deep_link":"`/agentstack-host-site` + `agentstack-commerce` skill","minimum_domains":["hosting","payments"],"optional_domains":[],"do_not_add_unless_asked":["business.create_composite"]},{"id":"social","name":"Social Platform","signals":["messenger_polling","friend_requests","channels","public_index"],"prompt":"agentstack_use_case_social","recipe_ids":["user_profiles_system","content_feed_basic","messaging_system"],"mcp_recipe_id":"mcp_bots_simulate","flow_id":"messenger_dm","sdk_hint":null,"showcase_key":"helpdesk-bot","deep_link":"`agentstack-messenger` skill · `social.chat.*`","minimum_domains":["social"],"optional_domains":[],"do_not_add_unless_asked":["business.create_composite"]},{"id":"backend_api","name":"Backend API","signals":["rest_crud","webhooks","automation","background_jobs"],"prompt":"agentstack_use_case_backend_api","recipe_ids":["rest_api_crud","webhook_system","background_jobs"],"mcp_recipe_id":"mcp_session_setup","flow_id":"connect_api_key_60s","sdk_hint":"sdk.protocol","showcase_key":null,"deep_link":"recipe `mcp_session_setup` · `sdk.protocol`","minimum_domains":["projects","auth"],"optional_domains":[],"do_not_add_unless_asked":["hosting.site.quick_start","crm.upsert_contact"]},{"id":"project_setup","name":"Project Setup & Mass Configuration","signals":["project_bootstrap","economy_setup","buff_templates_library","logic_rules_battery","scheduler_configuration","api_keys_provisioning","fap_configuration","mass_buff_application","bulk_user_updates"],"prompt":"agentstack_use_case_project_setup","recipe_ids":["project_economy","saas_trial_system"],"mcp_recipe_id":"mcp_read_bootstrap","flow_id":null,"sdk_hint":"getCapabilityMatrix","showcase_key":null,"deep_link":"`/agentstack-capability-matrix` · recipe `mcp_read_bootstrap`","minimum_domains":[],"optional_domains":[],"do_not_add_unless_asked":[]},{"id":"static_site","name":"Static Site / Landing","signals":["landing","portfolio","html","zip","publish"],"prompt":"agentstack_hosting_storefront","recipe_ids":["mcp_hosting_quickstart"],"mcp_recipe_id":"mcp_hosting_quickstart","flow_id":"hosting_deploy_publish","sdk_hint":"sdk.hosting.quickStart","showcase_key":"creator_portfolio","deep_link":"`/agentstack-host-site`","minimum_domains":["hosting"],"optional_domains":[],"do_not_add_unless_asked":["business.create_composite","crm.upsert_contact"]},{"id":"hosted_site_edit","name":"Edit published hosted site","signals":["edit site","change site","existing site","rollback","откат","изменить сайт","alterar site"],"prompt":"agentstack_hosting_edit_site","recipe_ids":["mcp_hosting_edit_site_safe"],"mcp_recipe_id":"mcp_hosting_edit_site_safe","flow_id":"hosting_edit_site_safe","sdk_hint":"sdk.hosting.quickStart","showcase_key":"creator_portfolio","deep_link":"prompt `agentstack_hosting_edit_site` · recipe `mcp_hosting_edit_site_safe`","minimum_domains":["hosting"],"optional_domains":[],"do_not_add_unless_asked":["hosting.site.quick_start"]},{"id":"bot_channel","name":"Bot Channel","signals":["telegram","whatsapp","bot studio","inbound message"],"prompt":"agentstack_bots_studio","recipe_ids":["mcp_bots_simulate"],"mcp_recipe_id":"mcp_bots_simulate","flow_id":"bot_go_live","sdk_hint":null,"showcase_key":"helpdesk-bot","deep_link":"recipe `mcp_bots_simulate` · Bot Studio","minimum_domains":[],"optional_domains":[],"do_not_add_unless_asked":[]},{"id":"showcase_portfolio_storefront","name":"Portfolio storefront (hosted /s/)","signals":["yacht","brokerage","lash","mebel","pulseid","doors","dveri","anatoly","portfolio tenant","independent_tenant","/s/1611","/s/1589","/s/1928","/s/1873"],"prompt":"agentstack_showcase_ops","recipe_ids":["mcp_showcase_catalog_safe"],"mcp_recipe_id":"mcp_showcase_catalog_safe","flow_id":"UF_SHOWCASE_CATALOG","sdk_hint":"sdk.hosting.quickStart","showcase_key":"morandi-yachts","deep_link":null,"minimum_domains":[],"optional_domains":[],"do_not_add_unless_asked":[]},{"id":"migrate_legacy","name":"Migrate Legacy Stack","signals":["supabase","firebase","auth0","stripe migration"],"prompt":null,"recipe_ids":[],"mcp_recipe_id":"mcp_session_setup","flow_id":null,"sdk_hint":"sdk.protocol","showcase_key":null,"deep_link":"`agentstack-migrator` agent","minimum_domains":[],"optional_domains":[],"do_not_add_unless_asked":[]},{"id":"hosted_vertical_saas","name":"Hosted Vertical SaaS","signals":["editflow","hosted workspace","vertical tenant","/s/","kanban","crm board","freelancer workspace"],"prompt":"agentstack_hosted_vertical","recipe_ids":["mcp_hosted_vertical_bootstrap","mcp_crm_contact_deal"],"mcp_recipe_id":"mcp_hosted_vertical_bootstrap","flow_id":null,"sdk_hint":"@agentstack/hosted-wire","showcase_key":null,"deep_link":"`agentstack-hosted-vertical` skill · `hosted-vertical/AGENTS.md` · `vertical_workspace.bootstrap` · `publish_editflow_hosted.py`","minimum_domains":[],"optional_domains":[],"do_not_add_unless_asked":[]},{"id":"service_business","name":"Service business","signals":["cleaning business","booking","клининг","cleaning","clinic","salon","услуг","serviço"],"prompt":"agentstack_crm_workspace","recipe_ids":["mcp_read_bootstrap"],"mcp_recipe_id":"mcp_read_bootstrap","flow_id":"crm","sdk_hint":null,"showcase_key":null,"deep_link":null,"minimum_domains":["crm"],"do_not_add_unless_asked":["hosting.site.quick_start"],"optional_domains":["logic","payments"],"recommended_playbook":"service_business_v1","success_criteria":["primary_public_url","crm_ready"]},{"id":"ai_product","name":"AI product","signals":["ai app","knowledge base product","ai product","ии продукт","produto de ia"],"prompt":"agentstack_knowledge_mentor","recipe_ids":["mcp_knowledge_ingest"],"mcp_recipe_id":"mcp_knowledge_ingest","flow_id":"knowledge","sdk_hint":null,"showcase_key":null,"deep_link":null,"minimum_domains":["knowledge"],"do_not_add_unless_asked":["business.create_composite"],"optional_domains":[],"recommended_playbook":"saas_build_v1"},{"id":"marketplace","name":"Marketplace","signals":["marketplace","listings","bazaar","маркетплейс","mercado"],"prompt":"agentstack_commerce_flows","recipe_ids":[],"mcp_recipe_id":"mcp_session_setup","flow_id":"payments","sdk_hint":null,"showcase_key":null,"deep_link":null,"minimum_domains":["payments"],"do_not_add_unless_asked":["business.create_composite"],"optional_domains":[]},{"id":"internal_tool","name":"Internal tool","signals":["internal tool","back office","внутренняя","ferramenta interna"],"prompt":"agentstack_session_setup","recipe_ids":["mcp_session_setup"],"mcp_recipe_id":"mcp_session_setup","flow_id":"session","sdk_hint":null,"showcase_key":null,"deep_link":null,"minimum_domains":["projects"],"do_not_add_unless_asked":["hosting.site.quick_start"],"optional_domains":[]},{"id":"community","name":"Community","signals":["community","forum","сообщество","comunidade"],"prompt":"agentstack_social_messenger","recipe_ids":[],"mcp_recipe_id":"mcp_session_setup","flow_id":null,"sdk_hint":null,"showcase_key":null,"deep_link":null,"minimum_domains":["bots"],"do_not_add_unless_asked":["payments.create_payment"],"optional_domains":[]},{"id":"key2unity_auth_portal","name":"Key2Unity auth portal","signals":["key2unity","ключ к единству","auth portal","shell_mode auth_portal","/s/1444/key2unity","activate_site_url"],"prompt":"agentstack_key2unity_site","recipe_ids":["mcp_key2unity_auth_portal","mcp_tenant_bots_heal_verify"],"mcp_recipe_id":"mcp_key2unity_auth_portal","flow_id":null,"sdk_hint":"@agentstack/hosted-wire/activateSession","showcase_key":"key2unity","deep_link":null,"minimum_domains":[],"optional_domains":[],"do_not_add_unless_asked":[]},{"id":"support_bot","name":"Support bot","signals":["support bot","helpdesk","бот поддержки","bot de suporte"],"prompt":"agentstack_bots_studio","mcp_recipe_id":"mcp_bots_simulate","minimum_domains":["bots"],"do_not_add_unless_asked":["crm.create_deal"],"deep_link":null,"optional_domains":[]},{"id":"knowledge_assistant","name":"Knowledge assistant","signals":["knowledge assistant","база знаний","assistente de conhecimento"],"prompt":"agentstack_knowledge_mentor","mcp_recipe_id":"mcp_knowledge_ingest","minimum_domains":["knowledge"],"do_not_add_unless_asked":["hosting.site.quick_start"],"deep_link":null,"optional_domains":[]},{"id":"agency","name":"Agency","signals":["agency","агентство","agência"],"prompt":"agentstack_crm_workspace","mcp_recipe_id":"mcp_crm_contact_deal","minimum_domains":["crm"],"do_not_add_unless_asked":["business.create_composite"],"deep_link":null,"optional_domains":[]},{"id":"freelancer","name":"Freelancer","signals":["freelancer","фриланс","autônomo","autonomo"],"prompt":"agentstack_hosted_vertical","mcp_recipe_id":"mcp_hosted_vertical_bootstrap","minimum_domains":["projects"],"do_not_add_unless_asked":["payments.create_payment"],"deep_link":null,"optional_domains":[]},{"id":"content_site","name":"Content site","signals":["blog","content site","блог","conteúdo","conteudo"],"prompt":"agentstack_hosting_static_landing","mcp_recipe_id":"mcp_hosting_quickstart","minimum_domains":["hosting"],"do_not_add_unless_asked":["business.create_composite","crm.upsert_contact"],"deep_link":null,"optional_domains":[]}]},"client_hints":{"gpt_actions_body":"{ \"tool\": \"<action>\", \"params\": {} }","single_action_body":"{ \"action\": \"<action>\", \"params\": {} }","jsonrpc_steps_body":"{ \"steps\": [{ \"action\": \"<action>\", \"params\": {} }] }"}}}