Audience: AI agents using agentstack.execute via MCP
How to use: Find the scenario closest to your task, adapt the JSON, run it.
All actions are valid step.action values unless marked REST-only.
Full action catalog: GET /mcp/actions
Scenarios below use tenant-app buff SKUs (your product tiers). Do not conflate with AgentStack platform planes:
| Plane | Tiers | entity_kind |
|---|---|---|
| Personal (user) | free, premium ($15), vip ($45) | user |
| Business (project) | sandbox → launch → business → scale → enterprise | project |
Personal Premium/VIP never raises project API/member/sandbox quotas. Platform upgrade: https://agentstack.tech/pricing · SoT: shared/subscription/ · MCP copy: shared/mcp/subscription_plane_copy.py
scheduler.create_task accepts cron_expression as cron, run_at as execute_at (now is the current UTC time), and task_type once / cron as one_time / recurring. payload.action runs only when it is a registered scheduler action (storage.cleanup_temp, payments.reconcile_pending, and the list returned as registered_scheduler_actions). Any other name is stored and does nothing when the task fires. payments.create charges card, stripe, or tochka (payment_method is required) and returns status: pending. A same-batch if on completed skips the following steps; use pending to continue after the charge is accepted, then payments.get for a settled completed. A wallet credit is wallets.deposit. Currencies are USD, EUR, RUB, BRL. The payer is the session user. Step if may be {"from": "step.result.field", "op": "equals", "value": ...} or "op": "exists". A buff effect key without a data. prefix is stored as data.<key> (xp_multiplier → data.xp_multiplier). $user_id and $project_id are filled from context when that key is set; a whole $name keeps the context type. Other $tokens stay literal until the caller replaces them. Chain a previous step with {"from": "step.result.field"}, not $step_field. A list row is result.contacts[0].id (or result.contacts.0.id).
- Complete Project Bootstrap
- SaaS Trial → Subscription → Upgrade
- Game Economy — Currencies, Wallets, Rewards
- Loyalty & Rewards Program
- E-commerce Checkout Flow
- AI Automation Pipeline
- Content Platform with Access Control
- Social Community Activation
- Multi-tenant B2B Onboarding
- Event-driven Marketing Campaign
- Usage-based Billing with Auto-throttling
- Player Matchmaking & Seasonal Events
- Read-only session bootstrap
- Seller one-click
- Generation safe mutation + canary promote
- Business composite bootstrap
- Services inquiry + downstream MCP
- Platform grant + tenant subscription monetization
Problem: Start from zero — provision a project with economy, RBAC, logic rules, API keys, and scheduled maintenance in a single session.
Tool chain: projects.create_project_anonymous → assets.create ×N →
wallets.create → wallets.deposit → buffs.create_buff (welcome) →
logic.create (rules) → scheduler.create_task (maintenance) →
apikeys.create (restricted) → rbac.assign_role
{
"steps": [
{
"id": "project",
"action": "projects.create_project_anonymous",
"params": {
"name": "My App",
"data": {
"config": {"currency": "credits", "version": "1.0"}
}
}
},
{
"id": "asset_credits",
"action": "assets.create",
"params": {
"name": "Credits",
"type": "currency",
"project_id": {"from": "project.result.project_id"},
"data": {"symbol": "CR", "decimals": 0}
}
},
{
"id": "asset_premium",
"action": "assets.create",
"params": {
"name": "Premium Gems",
"type": "currency",
"project_id": {"from": "project.result.project_id"},
"data": {"symbol": "GEM", "decimals": 0, "premium": true}
}
},
{
"id": "wallet",
"action": "wallets.create",
"params": {
"name": "Main Wallet",
"currency": "credits",
"project_id": {"from": "project.result.project_id"}
}
},
{
"id": "seed_balance",
"action": "wallets.deposit",
"params": {
"wallet_id": {"from": "wallet.result.wallet_id"},
"amount": 1000,
"description": "Initial seed balance"
}
},
{
"id": "welcome_buff",
"action": "buffs.create_buff",
"params": {
"name": "Welcome Bonus",
"description": "7-day welcome period with boosted rates",
"duration_days": 7,
"effects": {"xp_multiplier": 2.0, "welcome": true},
"revert_on_expire": true,
"project_id": {"from": "project.result.project_id"}
}
},
{
"id": "daily_reward_rule",
"action": "logic.create",
"params": {
"name": "Daily Login Reward",
"description": "Award credits on daily login",
"triggers": [{"type": "command", "command": "event.daily_login"}],
"space": [
{
"processor": "field_operations_processor",
"action": "add",
"parameters": {"field1": "user.data.credits", "field2": 10, "result_field": "user.data.credits"}
}
],
"enabled": true,
"project_id": {"from": "project.result.project_id"}
}
},
{
"id": "cleanup_task",
"action": "scheduler.create_task",
"params": {
"name": "Weekly Cleanup",
"task_type": "cron",
"cron_expression": "0 3 * * 0",
"payload": {"action": "storage.cleanup_temp"},
"project_id": {"from": "project.result.project_id"}
}
},
{
"id": "agent_key",
"action": "apikeys.create",
"params": {
"name": "AI Agent Key",
"service_caps": ["payments", "scheduler"],
"project_id": {"from": "project.result.project_id"}
}
}
]
}Key synergies:
project_idflows from step 1 through all subsequent steps via{"from": "..."}assets.createx2 = multi-currency economy in one batchbuffs.create_buffwithoutapply= template ready for all new usersapikeys.createwithservice_caps= safe agent key that can pay + schedule
Problem: User starts a free trial, converts to paid, and later upgrades their plan. Each transition must be atomic with automatic revert on failure.
{
"steps": [
{
"id": "trial_buff",
"action": "buffs.create_buff",
"params": {
"name": "Pro Trial",
"duration_days": 14,
"effects": {
"plan": "pro",
"api_calls_limit": 10000,
"team_members_limit": 5
},
"revert_on_expire": true,
"on_expire": [{"command": "event.trial_expired", "payload": {"user_id": "$user_id"}}]
}
},
{
"id": "apply_trial",
"action": "buffs.apply_buff",
"params": {
"buff_id": {"from": "trial_buff.result.buff_id"},
"entity_id": "$user_id",
"entity_kind": "user"
}
},
{
"id": "trial_reminder",
"action": "scheduler.create_task",
"params": {
"name": "Trial expiry reminder",
"task_type": "once",
"run_at": "$trial_end_minus_2days",
"payload": {"template": "trial_expiring_soon", "user_id": "$user_id"}
}
}
]
}Canonical (tenant SaaS):
buffs.create_buff(SKU template) →commerce.sell.activate→payments.create(intent=subscription,metadata.recipient_project_id) → webhook/C24 auto-grant. Manual comp:buffs.grant_tenant_subscription. Do not chainpayments.create→buffs.apply_buff.
{
"steps": [
{
"id": "remove_trial",
"action": "buffs.revert_buff",
"params": {
"application_id": "$trial_application_id",
"entity_id": "$user_id",
"entity_kind": "user"
}
},
{
"id": "go_live",
"action": "commerce.sell.activate",
"params": {
"project_id": "$tenant_project_id",
"subscription_entitlement": true,
"preset_inputs": {"buff_template_id": "$pro_buff_template_id"}
}
},
{
"id": "charge",
"action": "payments.create",
"params": {
"amount": 29.0,
"currency": "USD",
"intent": "subscription",
"metadata": {
"plan": "pro_monthly",
"recipient_project_id": "$tenant_project_id"
}
}
},
{
"id": "verify_grant",
"action": "buffs.list_active_buffs",
"params": {
"entity_id": "$user_id",
"entity_kind": "user",
"project_id": "$tenant_project_id"
}
},
{
"id": "renewal_task",
"action": "scheduler.create_task",
"params": {
"name": "Monthly renewal",
"task_type": "once",
"run_at": "$next_billing_date",
"payload": {"action": "process_renewal", "user_id": "$user_id", "plan": "pro_monthly"}
}
}
]
}Paid upgrade: new checkout with upgraded SKU → webhook/C24 grant. Manual/support:
buffs.grant_tenant_subscriptionwith newplan_id. Platform operator tiers:buffs.grant_subscription(PID=1).
{
"steps": [
{
"id": "prorate_charge",
"action": "payments.create",
"params": {
"amount": 71.0,
"currency": "USD",
"intent": "subscription",
"metadata": {
"from_plan": "pro_monthly",
"to_plan": "enterprise_monthly",
"recipient_project_id": "$tenant_project_id"
}
}
},
{
"id": "cancel_pro",
"action": "buffs.cancel_buff",
"params": {
"application_id": "$pro_application_id",
"entity_id": "$user_id",
"entity_kind": "user"
}
},
{
"id": "verify_upgrade",
"action": "buffs.list_active_buffs",
"params": {
"entity_id": "$user_id",
"entity_kind": "user",
"project_id": "$tenant_project_id"
}
}
]
}Key synergies:
payments.create+ifcondition = payment-gated buff activation- Paid upgrade: new checkout → webhook/C24 grant; manual:
buffs.grant_tenant_subscriptionwith newplan_id scheduler.create_taskfor each future event = event-driven billing
Problem: Set up a game economy with soft/hard currencies, reward logic, daily bonuses, and in-app purchases.
{
"steps": [
{
"id": "soft_currency",
"action": "assets.create",
"params": {"name": "Gold", "type": "currency", "data": {"symbol": "G", "earnable": true}}
},
{
"id": "hard_currency",
"action": "assets.create",
"params": {"name": "Gems", "type": "currency", "data": {"symbol": "GEM", "purchasable": true, "premium": true}}
},
{
"id": "player_wallet",
"action": "wallets.create",
"params": {"name": "Player Wallet", "currency": "gold"}
},
{
"id": "starter_bonus",
"action": "wallets.deposit",
"params": {
"wallet_id": {"from": "player_wallet.result.wallet_id"},
"amount": 500,
"description": "Starter gold bonus"
}
},
{
"id": "daily_reward_logic",
"action": "logic.create",
"params": {
"name": "Daily Login Reward",
"triggers": [{"type": "command", "command": "game.daily_login"}],
"space": [
{
"processor": "field_operations_processor",
"action": "add",
"parameters": {"field1": "user.data.gold", "field2": 50, "result_field": "user.data.gold"}
},
{
"processor": "field_operations_processor",
"action": "add",
"parameters": {"field1": "user.data.daily_streak", "field2": 1, "result_field": "user.data.daily_streak"}
}
],
"enabled": true
}
},
{
"id": "streak_bonus_logic",
"action": "logic.create",
"params": {
"name": "Streak Bonus (7-day)",
"triggers": [{"type": "command", "command": "game.daily_login"}],
"conditions": [{"field": "user.data.daily_streak", "op": "equals", "value": 7}],
"space": [
{
"processor": "field_operations_processor",
"action": "add",
"parameters": {"field1": "user.data.gems", "field2": 10, "result_field": "user.data.gems"}
},
{
"processor": "field_operations_processor",
"action": "set",
"parameters": {"field": "user.data.daily_streak", "value": 0}
}
],
"enabled": true
}
},
{
"id": "iap_gem_pack",
"action": "assets.create",
"params": {
"name": "Gem Pack 100",
"type": "iap_product",
"data": {"gems_amount": 100, "price_usd": 0.99, "sku": "gems_100"}
}
},
{
"id": "seasonal_event_buff",
"action": "buffs.create_buff",
"params": {
"name": "Double XP Weekend",
"duration_days": 2,
"effects": {"xp_multiplier": 2.0, "gold_multiplier": 1.5},
"revert_on_expire": true
}
}
]
}Purchasing gems (IAP flow):
{
"steps": [
{
"id": "pay",
"action": "payments.create",
"params": {"amount": 0.99, "currency": "USD", "description": "Gem Pack 100", "payment_method": "card", "metadata": {"sku": "gems_100"}}
},
{
"id": "deposit_gems",
"action": "wallets.deposit",
"params": {
"wallet_id": "$user_gem_wallet_id",
"amount": 100,
"description": "Gem Pack 100 purchase"
},
"if": {"from": "pay.result.status", "op": "equals", "value": "pending"}
}
]
}Key synergies:
assets.createdefines economy schema;wallets.depositfunds itlogic.createwith conditions = streak/combo reward enginepayments.create+if+wallets.deposit= verified IAP flowbuffs.create_buffas event template = activate for all users with oneapply_buff
Problem: Track points, award badges, tier-based perks, point expiry, and redemption for any type of app.
{
"steps": [
{
"id": "points_asset",
"action": "assets.create",
"params": {"name": "Loyalty Points", "type": "points", "data": {"symbol": "LP", "expiry_days": 365}}
},
{
"id": "bronze_buff",
"action": "buffs.create_buff",
"params": {
"name": "Bronze Member",
"effects": {"tier": "bronze", "discount_pct": 5, "priority_support": false},
"revert_on_expire": false
}
},
{
"id": "silver_buff",
"action": "buffs.create_buff",
"params": {
"name": "Silver Member",
"effects": {"tier": "silver", "discount_pct": 10, "priority_support": true},
"revert_on_expire": false
}
},
{
"id": "gold_buff",
"action": "buffs.create_buff",
"params": {
"name": "Gold Member",
"effects": {"tier": "gold", "discount_pct": 20, "priority_support": true, "free_shipping": true},
"revert_on_expire": false
}
},
{
"id": "earn_points_rule",
"action": "logic.create",
"params": {
"name": "Earn points on purchase",
"triggers": [{"type": "command", "command": "event.purchase_completed"}],
"space": [
{
"processor": "field_operations_processor",
"action": "add",
"parameters": {
"field1": "user.data.loyalty_points",
"field2": 10,
"result_field": "user.data.loyalty_points"
}
}
],
"enabled": true
}
},
{
"id": "tier_upgrade_rule",
"action": "logic.create",
"params": {
"name": "Auto tier upgrade",
"triggers": [{"type": "command", "command": "loyalty.promote_silver"}],
"space": [
{
"processor": "field_operations_processor",
"action": "set",
"parameters": {"field": "user.data.tier", "value": "silver"}
}
],
"enabled": true
}
},
{
"id": "expiry_scheduler",
"action": "scheduler.create_task",
"params": {
"name": "Monthly points expiry check",
"task_type": "cron",
"cron_expression": "0 2 1 * *",
"payload": {"action": "expire_loyalty_points", "expiry_days": 365}
}
}
]
}Key synergies:
assets.create= points schema with metadatabuffs.create_buffx3 = tier templates, apply instantly to any userlogic.creatematchestype: command. Emitloyalty.promote_silverwhen the app decides the threshold.field2is a number; the processor does not readfrom_event.scheduler.create_taskwith cron = automatic expiry without extra code
Problem: Read the inventory leaf, accept payment, credit loyalty points, and
schedule a follow-up. Stock writes stay on projects.patch_data.
{
"steps": [
{
"id": "stock",
"action": "projects.get_data",
"params": {
"project_id": "$project_id",
"path": "commerce.inventory"
}
},
{
"id": "payment",
"action": "payments.create",
"params": {
"amount": "$order_total",
"currency": "USD",
"description": "Order #$order_id",
"payment_method": "card",
"metadata": {"order_id": "$order_id", "product_ids": "$product_ids"}
},
"if": {"from": "stock.result.value", "op": "exists"}
},
{
"id": "add_loyalty_points",
"action": "wallets.deposit",
"params": {
"wallet_id": "$user_loyalty_wallet_id",
"amount": {"from": "payment.result.amount"},
"description": "Loyalty points for order"
},
"if": {"from": "payment.result.status", "op": "equals", "value": "pending"}
},
{
"id": "fulfillment_task",
"action": "scheduler.create_task",
"params": {
"name": "Fulfill order $order_id",
"task_type": "once",
"run_at": "now",
"payload": {"action": "trigger_fulfillment", "order_id": "$order_id", "payment_id": {"from": "payment.result.payment_id"}}
},
"if": {"from": "payment.result.status", "op": "equals", "value": "pending"}
},
{
"id": "checkout_health",
"action": "analytics.project_snapshot",
"params": {"include": ["activity", "finance", "product_events"]}
}
]
}Key synergies:
projects.get_dataoncommerce.inventoryis the stock read.op: existscontinues only when that leaf is present. A stock change isprojects.patch_dataon the same path, notcommands.execute.wallets.deposit= loyalty points on every purchase (no extra service)scheduler.create_taskwithrun_at: nowstores a one-time task.trigger_fulfillmentis not a registered action, so the create response setsaction_registeredto false.analytics.project_snapshotreads project health KPIs after checkout. It does not record a purchase.
Problem: Build a self-maintaining pipeline: monitor usage, auto-scale limits, alert on thresholds, and run cleanup tasks.
{
"steps": [
{
"id": "usage_monitor_rule",
"action": "logic.create",
"params": {
"name": "API quota monitor",
"triggers": [{"type": "command", "command": "system.api_call_completed"}],
"space": [
{
"processor": "field_operations_processor",
"action": "add",
"parameters": {"field1": "project.data.api_calls_today", "field2": 1, "result_field": "project.data.api_calls_today"}
}
],
"enabled": true
}
},
{
"id": "threshold_alert_rule",
"action": "logic.create",
"params": {
"name": "Usage threshold alert",
"triggers": [{"type": "command", "command": "usage.quota_warning"}],
"space": [
{
"processor": "field_operations_processor",
"action": "set",
"parameters": {"field": "project.data.quota_warning_sent", "value": true}
}
],
"enabled": true
}
},
{
"id": "auto_scale_buff",
"action": "buffs.create_buff",
"params": {
"name": "Emergency quota boost",
"duration_days": 1,
"effects": {"api_calls_limit": 20000, "overage_mode": true},
"revert_on_expire": true
}
},
{
"id": "daily_reset_task",
"action": "scheduler.create_task",
"params": {
"name": "Daily API counter reset",
"task_type": "cron",
"cron_expression": "0 0 * * *",
"payload": {
"action": "reset_counter",
"fields": ["project.data.api_calls_today", "project.data.quota_warning_sent"]
}
}
},
{
"id": "weekly_analytics_task",
"action": "scheduler.create_task",
"params": {
"name": "Weekly usage report",
"task_type": "cron",
"cron_expression": "0 9 * * 1",
"payload": {"action": "generate_usage_report", "send_email": true}
}
},
{
"id": "stale_data_cleanup",
"action": "scheduler.create_task",
"params": {
"name": "Stale session cleanup",
"task_type": "cron",
"cron_expression": "0 4 * * *",
"payload": {"action": "storage.cleanup_temp"}
}
}
]
}Key synergies:
logic.createcounts onsystem.api_call_completed. The warning rule runs when something emitsusage.quota_warning.buffs.create_buff(emergency boost) ready to apply whenthreshold_alert_rulefires- Daily cleanup uses
storage.cleanup_temp.reset_counterandgenerate_usage_reportare not registered actions; create returnsaction_registered: false. - All steps reference
project_idfrom context — no explicit passing needed
Problem: Create a content library, gate premium content behind subscriptions, track consumption, and manage editorial permissions.
{
"steps": [
{
"id": "free_tier_buff",
"action": "buffs.create_buff",
"params": {
"name": "Free Access",
"effects": {"content_tier": "free", "articles_per_month": 3, "downloads": 0},
"revert_on_expire": false
}
},
{
"id": "premium_buff",
"action": "buffs.create_buff",
"params": {
"name": "Premium Subscription",
"duration_days": 30,
"effects": {"content_tier": "premium", "articles_per_month": 999, "downloads": 50},
"revert_on_expire": true,
"on_expire": [{"command": "event.premium_expired"}]
}
},
{
"id": "content_asset_pdf",
"action": "assets.create",
"params": {
"name": "Annual Report 2025",
"type": "document",
"data": {"tier": "premium", "format": "pdf", "file_size_mb": 4.2}
}
},
{
"id": "article_limit_rule",
"action": "logic.create",
"params": {
"name": "Article consumption tracker",
"triggers": [{"type": "command", "command": "content.article_read"}],
"space": [
{
"processor": "field_operations_processor",
"action": "add",
"parameters": {"field1": "user.data.articles_read_this_month", "field2": 1, "result_field": "user.data.articles_read_this_month"}
}
],
"enabled": true
}
},
{
"id": "fap_policy",
"action": "data_access.set_policy",
"params": {
"resources": {
"premium_content": {
"default_access": "deny",
"fields": {
"body": {"read": "authenticated", "write": "deny", "condition": "{{user.role}} == 'admin'"},
"preview": "authenticated"
}
}
}
}
},
{
"id": "editor_role",
"action": "rbac.assign_role",
"params": {"user_id": "$editor_user_id", "role": "editor"}
},
{
"id": "monthly_reset",
"action": "scheduler.create_task",
"params": {
"name": "Reset monthly article counts",
"task_type": "cron",
"cron_expression": "0 0 1 * *",
"payload": {"action": "reset_monthly_counters", "field": "user.data.articles_read_this_month"}
}
}
]
}Key synergies:
buffs.create_buff(free/premium templates) +data_access.set_policy= content gating. Field descriptors aredeny/authenticated/{read, write, condition}. A condition is a string the evaluator already runs ({{user.role}} == 'admin'). An objectallow_ifis stored asdeny.assets.create= content catalog with metadatalogic.createcounter +scheduler.create_taskreset = metered access modelrbac.assign_role= editorial permissions
Problem: Onboard a user into a social community: create profile, join a channel, send first welcome message, connect with community bot.
{
"steps": [
{
"id": "publish_profile",
"action": "auth.update_profile",
"params": {
"display_name": "$user_name",
"bio": "$bio"
}
},
{
"id": "join_general",
"action": "social.channel_invites.redeem",
"params": {"token": "$general_channel_invite_token"}
},
{
"id": "welcome_message",
"action": "social.chat.post",
"params": {
"channel_id": "$general_channel_id",
"text": "Hey everyone! I just joined."
}
},
{
"id": "friend_bot",
"action": "social.friends.request",
"params": {"target_user_id": "$community_bot_user_id"}
},
{
"id": "index_profile",
"action": "social.public.publish",
"params": {
"home_project_id": 1,
"kind": "channels",
"channel_id": "$general_channel_id"
}
},
{
"id": "onboarding_buff",
"action": "buffs.apply_buff",
"params": {
"buff_id": "$onboarding_buff_template_id",
"entity_id": "$user_id",
"entity_kind": "user"
}
}
]
}RAG-enhanced community search:
{
"steps": [
{
"id": "index_message",
"action": "rag.document_add",
"params": {
"collection_id": "$community_rag_collection_id",
"text": "$message_text",
"metadata": {"author": "$user_id", "channel": "$channel_id", "ts": "$timestamp"}
}
},
{
"id": "search",
"action": "rag.search",
"params": {
"collection_id": "$community_rag_collection_id",
"query": "how to get started with the API",
"limit": 5
}
}
]
}Key synergies:
auth.update_profilesets the display name.social.public.publishlists a channel, it does not store a user bio. Avatar upload isPOST /api/profile/avatar.social.channel_invites.redeem= join any channel with single-use tokenbuffs.apply_buff= onboarding perks applied automaticallyrag.document_addon chat messages = searchable community knowledge base
Problem: Enterprise sale — provision a new tenant organization, set up their team, configure feature flags per contract tier, and hand off API credentials.
{
"steps": [
{
"id": "org_project",
"action": "projects.create_project",
"params": {
"name": "$company_name Workspace",
"data": {
"config": {
"org_id": "$crm_org_id",
"contract_tier": "enterprise",
"seats": 50
}
}
}
},
{
"id": "admin_role",
"action": "rbac.assign_role",
"params": {
"user_id": "$admin_user_id",
"role": "admin",
"project_id": {"from": "org_project.result.project_id"}
}
},
{
"id": "enterprise_buff",
"action": "buffs.apply_buff",
"params": {
"buff_id": "$enterprise_tier_buff_id",
"entity_id": {"from": "org_project.result.project_id"},
"entity_kind": "project"
}
},
{
"id": "sso_key",
"action": "apikeys.create",
"params": {
"name": "$company_name SSO Integration",
"service_caps": ["analytics"],
"project_id": {"from": "org_project.result.project_id"}
}
},
{
"id": "agent_key",
"action": "apikeys.create",
"params": {
"name": "$company_name AI Agent",
"service_caps": ["payments", "scheduler"],
"project_id": {"from": "org_project.result.project_id"}
}
},
{
"id": "invite_team",
"action": "social.channel_invites.direct",
"params": {
"home_project_id": {"from": "org_project.result.project_id"},
"user_ids": "$team_user_ids",
"channel_id": "$org_channel_id"
}
},
{
"id": "fap_defaults",
"action": "data_access.apply_defaults_template",
"params": {"project_id": {"from": "org_project.result.project_id"}}
},
{
"id": "health_check_task",
"action": "scheduler.create_task",
"params": {
"name": "Weekly tenant health check",
"task_type": "cron",
"cron_expression": "0 8 * * 1",
"payload": {"action": "tenant_health_report", "project_id": {"from": "org_project.result.project_id"}}
}
}
]
}Key synergies:
projects.create_project+rbac.assign_role= full org with owner in 2 stepsbuffs.apply_buffonentity_kind: "project"= project-level enterprise featuresapikeys.createx2 with differentservice_caps= SSO key (analytics only) + AI key (payments + scheduler)data_access.apply_defaults_template= instant policy without manual setup
Problem: Run a time-limited campaign: bonus credits for purchases, double XP weekend, leaderboard tracking, and automatic campaign end.
{
"steps": [
{
"id": "campaign_buff",
"action": "buffs.create_buff",
"params": {
"name": "Summer Campaign 2025",
"duration_days": 7,
"effects": {
"bonus_credits_pct": 20,
"xp_multiplier": 2.0,
"campaign_active": true
},
"revert_on_expire": true,
"on_expire": [{"command": "event.campaign_ended", "payload": {"campaign_id": "summer_2025"}}]
}
},
{
"id": "apply_to_project",
"action": "buffs.apply_buff",
"params": {
"buff_id": {"from": "campaign_buff.result.buff_id"},
"entity_id": "$project_id",
"entity_kind": "project"
}
},
{
"id": "bonus_credits_rule",
"action": "logic.create",
"params": {
"name": "Campaign purchase bonus",
"triggers": [{"type": "command", "command": "event.purchase_completed"}],
"space": [
{
"processor": "field_operations_processor",
"action": "multiply",
"parameters": {
"field1": "event.purchase_amount",
"field2": 0.2,
"result_field": "user.data.bonus_credits"
}
}
],
"enabled": true
}
},
{
"id": "leaderboard_rule",
"action": "logic.create",
"params": {
"name": "Campaign leaderboard tracker",
"triggers": [{"type": "command", "command": "event.xp_earned"}],
"space": [
{
"processor": "field_operations_processor",
"action": "add",
"parameters": {"field1": "user.data.campaign_score", "field2": 1, "result_field": "user.data.campaign_score"}
}
],
"enabled": true
}
},
{
"id": "leaderboard_asset",
"action": "assets.create",
"params": {
"name": "Campaign Leaderboard Trophy",
"type": "achievement",
"data": {"campaign": "summer_2025", "rank_required": 1}
}
},
{
"id": "campaign_end_task",
"action": "scheduler.create_task",
"params": {
"name": "Campaign end: award trophies",
"task_type": "once",
"run_at": "$campaign_end_datetime",
"payload": {"action": "award_campaign_trophies", "asset_id": {"from": "leaderboard_asset.result.asset_id"}}
}
}
]
}Key synergies:
buffs.apply_buffon project = global state flag readable by all logic ruleslogic.createfires on the command name. A top-levelconditionsarray is not read by the matcher.assets.create(trophy) +scheduler.create_task(award) = automated prize distribution
Problem: Measure API usage, bill on consumption, auto-downgrade on non-payment, auto-upgrade limits when usage grows.
{
"steps": [
{
"id": "usage_counter_logic",
"action": "logic.create",
"params": {
"name": "Increment monthly API counter",
"triggers": [{"type": "command", "command": "system.api_call_authenticated"}],
"space": [
{
"processor": "field_operations_processor",
"action": "add",
"parameters": {"field1": "user.data.api_calls_this_month", "field2": 1, "result_field": "user.data.api_calls_this_month"}
}
],
"enabled": true
}
},
{
"id": "overage_detect_logic",
"action": "logic.create",
"params": {
"name": "Detect quota overage",
"triggers": [{"type": "command", "command": "system.api_call_authenticated"}],
"space": [
{
"processor": "field_operations_processor",
"action": "set",
"parameters": {"field": "user.data.quota_exceeded", "value": true}
}
],
"enabled": true
}
},
{
"id": "monthly_invoice_task",
"action": "scheduler.create_task",
"params": {
"name": "Monthly usage billing",
"task_type": "cron",
"cron_expression": "0 10 1 * *",
"payload": {
"action": "generate_and_charge_invoice",
"metric_field": "user.data.api_calls_this_month",
"rate_per_call": 0.001
}
}
},
{
"id": "throttle_buff",
"action": "buffs.create_buff",
"params": {
"name": "Quota Exceeded — Throttled",
"effects": {"rate_limit_rps": 1, "quota_exceeded": true},
"revert_on_expire": false,
"description": "Applied when user exceeds plan quota without upgrade"
}
},
{
"id": "reset_counter_task",
"action": "scheduler.create_task",
"params": {
"name": "Monthly counter reset",
"task_type": "cron",
"cron_expression": "0 0 1 * *",
"payload": {
"action": "reset_field",
"fields": ["user.data.api_calls_this_month", "user.data.quota_exceeded"]
}
}
}
]
}Key synergies:
logic.creatematchestype: commandonly. There is nofield_changetrigger.buffs.create_buff(throttle template) = instant apply when overage detectedscheduler.create_taskx2 = billing + reset in one setup call
Problem: Create a matchmaking system with ELO ratings, seasonal ranking resets, and tiered seasonal rewards.
{
"steps": [
{
"id": "season_buff",
"action": "buffs.create_buff",
"params": {
"name": "Season 1",
"duration_days": 90,
"effects": {"season": 1, "season_active": true, "elo_visible": true},
"revert_on_expire": true,
"on_expire": [{"command": "event.season_ended", "payload": {"season": 1}}]
}
},
{
"id": "apply_season",
"action": "buffs.apply_buff",
"params": {
"buff_id": {"from": "season_buff.result.buff_id"},
"entity_id": "$project_id",
"entity_kind": "project"
}
},
{
"id": "elo_update_rule",
"action": "logic.create",
"params": {
"name": "ELO update after match",
"triggers": [{"type": "command", "command": "game.match_completed"}],
"space": [
{
"processor": "field_operations_processor",
"action": "add",
"parameters": {"field1": "user.data.elo", "field2": 15, "result_field": "user.data.elo"}
},
{
"processor": "field_operations_processor",
"action": "add",
"parameters": {"field1": "user.data.season_points", "field2": 10, "result_field": "user.data.season_points"}
}
],
"enabled": true
}
},
{
"id": "gold_rank_reward",
"action": "assets.create",
"params": {
"name": "Season 1 Gold Badge",
"type": "badge",
"data": {"season": 1, "rank": "gold", "elo_threshold": 1800}
}
},
{
"id": "season_end_task",
"action": "scheduler.create_task",
"params": {
"name": "Season 1 end: distribute rewards + reset",
"task_type": "once",
"run_at": "$season_end_datetime",
"payload": {
"action": "season_end_processing",
"rank_asset_id": {"from": "gold_rank_reward.result.asset_id"},
"reset_field": "user.data.season_points"
}
}
},
{
"id": "matchmaking_rag_collection",
"action": "rag.collection_create",
"params": {
"name": "matchmaking_player_profiles",
"description": "Player skill profiles for semantic matchmaking"
}
}
]
}Key synergies:
buffs.apply_buffon project = global season state, readable by all ruleslogic.create= ELO updates without server codeassets.create(badge) +scheduler.create_task= automatic end-of-season awardsrag.collection_create= semantic player matching (add player profiles, search by skill tags)
Problem: A signed-in user needs to message a project's support team without joining a public channel.
Flow: Discover staff inbox capability via roles, read thread, send message (MCP mirrors REST).
{
"steps": [
{
"id": "roles",
"action": "social.support.inbox",
"params": {"project_id": "$home_project_id", "limit": 5}
},
{
"id": "history",
"action": "social.support.history",
"params": {"project_id": "$home_project_id", "limit": 50}
},
{
"id": "send",
"action": "social.support.send",
"params": {"project_id": "$home_project_id", "body": "I need help with billing."}
}
]
}Staff-only listing requires API key cap
project_supportonsocial.support.inbox; send/history use session RBAC inside the tool.
Tenant paid SKU: commerce.sell.activate → payments.create → webhook/C24 auto-grant
Tenant manual: buffs.grant_tenant_subscription
Platform operator: buffs.grant_subscription (context.project_id=1)
IAP / loyalty only: payments.create → (if completed) → buffs.apply_persistent_effect
logic.create (trigger: command) → field update → another command rule
buffs.create_buff (revert_on_expire) → buffs.apply_buff (entity_kind: project) → logic.create (reads buff effect)
scheduler.create_task (cron) → wallets.deposit OR payments.create (tenant subscription: webhook grant) OR buffs.apply_temporary_effect (non-subscription perks)
apikeys.create (service_caps: ["payments"]) → use returned api_key for payment-only agent
logic.create (counter) → scheduler.create_task (monthly reset) + buffs.create_buff (limit template)
generation.fork → projects.patch_data (sandbox only) → generation.diff → generation.gates → generation.promote
business.create_composite → business.get_org → business.apply_tariff (optional) → business.command_snapshot
| Axis | Sandbox generation (generation.*) |
Business organism (business.*) |
|---|---|---|
| Goal | Experiment with project config/DNA before production | Provision multi-project org (head + organ children) |
| Entry | generation.fork on an existing project |
business.create_composite greenfield |
| Promote / commit | generation.promote, generation.canary.advance |
business.apply_tariff, attach/detach organs — not generation promote |
| Read model | generation.status, generation.diff, generation.timeline |
business.get_org, business.command_snapshot |
| Wrong tool | Composite create for a one-off config tweak | generation.fork when you need CRM + storefront organs |
| Axis | hosting.release.promote |
generation.promote |
|---|---|---|
| Plane | Static hosting — immutable site bucket snapshots | 8DNA — sandbox environment production pointer |
| Typical pre-step | commerce.storefront.hosted_publish or hosting.release.snapshot |
generation.fork → mutate → generation.gates |
| Audit | hosting.release.list |
generation.timeline |
| Bridge | generation.hosting.release labels a snapshot with sandbox gen (preview; swap URL separately) |
Hosted vitrine publish is separate after generation promote |
Problem: Agent discovers a listing globally and completes purchase with internal USDT wallet.
REST chain (not MCP step.action for listing lifecycle):
GET /api/commerce/storefront/listings?scope=global&q=swordPOST /api/commerce/checkout/sessions+ headerIdempotency-KeyPOST /api/commerce/checkout/sessions/{id}/confirm
{
"listing_uuid": "$listing_uuid",
"rail": "wallet_internal"
}Merchant bulk (project-scoped):
assets.create(MCP) for catalog rowsPOST /api/commerce/marketplace/listings/bulkwithX-Project-ID
SDK:
await sdk.commerce.listStorefront({ scope: 'global' });
await sdk.commerce.checkout.createSession({ listing_uuid, rail: 'wallet_internal' });- Full action catalog:
GET /mcp/actions - Current key capabilities:
GET /mcp/discovery→api_key_context.service_caps - Project setup playbooks:
docs/MCP_PROJECT_SETUP_PLAYBOOKS.md - Commerce flows:
docs/MCP_ECONOMY_AND_COMMERCE_MAP.md - API key safety:
docs/API_KEY_SERVICE_CAPS.md
Problem: A 6-step batch with stopOnError dies on buffs.get_effective_limits or
apikeys.list (service_cap_denied) and never reaches quota.
Tool chain: auth.get_profile → projects.get_stats → buffs.get_effective_limits
→ storage.get_quota with continueOnError: true. Omit apikeys.list unless the
key has L1 api_keys. Omit entity_kind (string "user"/"project" only if passed).
Recipe: mcp_read_bootstrap sets continueOnError unless the request passes
stopOnError. The profile step asks for identity only (include_settings: false).
Prompt: agentstack_read_bootstrap. Default stopOnError for mutation batches stays true.
{
"steps": [],
"options": {"recipe_id": "mcp_read_bootstrap"}
}Problem: A creator wants to sell digital goods in one session — seed catalog, bind earnings wallet, publish a hosted vitrine, and verify release history.
Tool chain: commerce.sell.activate → commerce.storefront.hosted_publish →
hosting.release.list
{
"steps": [
{
"id": "activate",
"action": "commerce.sell.activate",
"params": {
"project_id": "$project_id",
"user_id": "$user_id",
"use_starter": true,
"publish_hosted": false,
"storefront_public": true,
"idempotency_key": "seller-one-click-v1"
}
},
{
"id": "publish",
"action": "commerce.storefront.hosted_publish",
"params": {
"project_id": "$project_id",
"user_id": "$user_id",
"bucket_name": "$store_slug"
},
"if": {"from": "activate.result.success", "op": "equals", "value": true}
},
{
"id": "releases",
"action": "hosting.release.list",
"params": {
"project_id": "$project_id",
"bucket_id": "$store_slug",
"limit": 10
},
"if": {"from": "publish.result.success", "op": "equals", "value": true}
}
]
}REST mirror: POST /api/commerce/sell/activate · POST /api/commerce/storefront/hosted/publish
Key synergies:
commerce.sell.activate= earnings wallet + seed + storefront index in one orchestrated pathpublish_hosted: falsein activate + separatehosted_publish= agent can inspect seed before vitrinehosting.release.listconfirms immutable release rows after publish (newest first)- Activation
share_kitreturnshosted_url,shop_url, and embed hints for operator handoff
Problem: Change project config in a sandbox, review diff and gates, then promote to production with optional canary traffic steps.
Tool chain: generation.list → generation.fork → projects.patch_data →
generation.diff → generation.gates → generation.promote → generation.canary.advance
{
"steps": [
{
"id": "envs",
"action": "generation.list",
"params": {"project_id": "$project_id"}
},
{
"id": "fork",
"action": "generation.fork",
"params": {
"project_id": "$project_id",
"source_project_id": "$project_id",
"env_name": "pricing-tweak",
"env_type": "sandbox"
}
},
{
"id": "mutate",
"action": "projects.patch_data",
"params": {
"project_id": "$project_id",
"env_uuid": {"from": "fork.result.env_uuid"},
"path": "config.pricing.pro_monthly_usd",
"value": 39
}
}
]
}{
"steps": [
{
"id": "diff",
"action": "generation.diff",
"params": {
"project_id": "$project_id",
"env_uuid_a": "$prod_env_uuid",
"env_uuid_b": {"from": "fork.result.anchor_uuid"}
}
},
{
"id": "gates",
"action": "generation.gates",
"params": {
"project_id": "$project_id",
"env_uuid": {"from": "fork.result.anchor_uuid"}
}
},
{
"id": "promote",
"action": "generation.promote",
"params": {
"project_id": "$project_id",
"env_uuid": {"from": "fork.result.anchor_uuid"},
"strategy": "immediate"
},
"if": {"from": "gates.result.all_passed", "op": "equals", "value": true}
},
{
"id": "canary_step",
"action": "generation.canary.advance",
"params": {
"project_id": "$project_id",
"env_uuid": {"from": "fork.result.anchor_uuid"}
},
"if": {"from": "promote.result.status", "op": "equals", "value": "rolling_out"}
}
]
}Key synergies:
generation.forkisolates mutations — production pointer unchanged until promotegeneration.diff+generation.gates= review-before-promote without custom CIgeneration.promotewithstrategy: "immediate"vs canaryrolling_out→generation.canary.advance- Manual gate pending →
generation.approvethen re-rungeneration.gates - Rollback path →
generation.canary.abort+generation.timelineaudit
Not
hosting.release.promote— that plane moves static site snapshots, not 8DNA sandboxes.
Problem: Greenfield business with organ children (CRM, storefront, bots, support), optional tariff, and a command-center read model in one batch.
Tool chain: business.create_composite → business.get_org → business.apply_tariff →
business.command_snapshot
{
"steps": [
{
"id": "composite",
"action": "business.create_composite",
"params": {
"name": "Acme Studio",
"organs": ["crm", "storefront", "bots", "support"],
"tariff_template_id": "starter"
}
},
{
"id": "org",
"action": "business.get_org",
"params": {
"project_id": {"from": "composite.result.head_project_id"}
}
},
{
"id": "tariff",
"action": "business.apply_tariff",
"params": {
"project_id": {"from": "composite.result.head_project_id"},
"template_id": "growth"
},
"if": {"from": "composite.result.success", "op": "equals", "value": true}
},
{
"id": "snapshot",
"action": "business.command_snapshot",
"params": {
"project_id": {"from": "composite.result.head_project_id"},
"include_integrations": true
}
}
]
}REST mirror: POST /api/business/composite
Key synergies:
business.create_composite= head project + organ child projects + org index in one sagabusiness.get_orgconfirmsconfig.orgchildren before downstream organ-specific MCPbusiness.command_snapshot= treasury + CRM summary + integration health (read-only aggregate)- Link existing standalone projects with
business.link_childinstead ofcreate_compositewhen adopting
Not
generation.fork— business organism is multi-project topology, not sandbox DNA.
Problem: A guest requests a professional-services quote on /services/:sku. The public BFF
is REST-only; staff follow up via CRM MCP on ecosystem project 1.
REST chain (guest — not agentstack.execute):
GET /api/public/services/catalogGET /api/public/services/skus/{sku_id}POST /api/public/services/inquiry→ 202 Accepted
{
"sku": "implementation-sprint",
"name": "Jane Doe",
"email": "jane@example.com",
"company": "Example Corp",
"message": "We need AgentStack CRM + storefront for 50 seats.",
"locale": "en"
}Downstream MCP (staff on ecosystem pid=1):
{
"steps": [
{
"id": "find_lead",
"action": "crm.search",
"params": {
"project_id": 1,
"q": "jane@example.com",
"limit": 5
}
},
{
"id": "contact_360",
"action": "crm.get_contact_360",
"params": {
"project_id": 1,
"contact_id": {"from": "find_lead.result.contacts[0].id"}
}
},
{
"id": "log_followup",
"action": "crm.log_activity",
"params": {
"project_id": 1,
"contact_id": {"from": "find_lead.result.contacts[0].id"},
"kind": "note",
"body": "Staff replied to services inquiry — scheduling discovery call."
}
},
{
"id": "deal",
"action": "crm.create_deal",
"params": {
"project_id": 1,
"contact_id": {"from": "find_lead.result.contacts[0].id"},
"title": "Implementation sprint — Example Corp",
"stage_id": "qualified"
}
}
]
}Key synergies:
- Inquiry upserts CRM contact + timeline note on ecosystem project 1 (not tenant scope)
- In-app notifications fan to pid=1 owner/admin with
action_href→/dev/projects/1/crm - Honeypot field
websitesilently accepts spam without persisting - Rate limit: 10 inquiries / hour / IP on
POST /inquiry - No MCP action for guest submit — use REST BFF; staff use
crm.*after acceptance
Gene: frontend.public.services_offers.gen1 · Hub: /services (not /pricing SaaS tiers)
Problem: Ecosystem operator grants AgentStack tiers (two planes) OR a tenant project sells subscription SKUs to end users.
| Rail | Who | Buff target | Entry |
|---|---|---|---|
| Platform operator | Lance / ecosystem op | user premium/vip OR project launch/business/scale | buffs.grant_subscription or prompt agentstack_platform_subscription_grant |
| Tenant monetization | Tenant sells to buyer | buyer entity_kind=user on tenant PID |
prompt agentstack_tenant_subscription_monetization |
| Tenant manual grant | Tenant operator (support/comp) | buyer entity_kind=user on tenant PID |
buffs.grant_tenant_subscription · prompt agentstack_tenant_buff_grant |
{
"context": { "project_id": 1 },
"steps": [
{
"action": "buffs.grant_subscription",
"params": { "plane": "personal", "tier": "vip", "entity_id": 1170, "verify": true }
}
]
}Project Scale example:
{
"action": "buffs.grant_subscription",
"params": { "plane": "project", "tier": "scale", "entity_id": 1444 }
}Energy side-effect: Personal premium/vip also tops up AI energy via shared/subscription/personal_energy_grant.py on buffs.apply_buff (not limits-only).
SoT: shared/mcp/platform_subscription_grant.py · resolve_platform_grant_buff_params
buffs.create_buff— tenant SKU template (before sell.activate)commerce.sell.activate—subscription_entitlement+preset_inputs.buff_template_idpayments.create—intent=subscription,metadata.recipient_project_id= tenant PID- Verify —
buffs.list_active_buffson buyer
Post-purchase:
- Card: webhook →
grant_tenant_plan_buff(shared/mcp/tenant_buff_grant.py) - Shop:
commerce.order.completed→ C24 inline hook incommerce_events.py
| SKU type | MCP action | SDK |
|---|---|---|
| Subscription buff | buffs.grant_tenant_subscription |
grantTenantSubscription() from @agentstack/sdk/commerce/subscription |
| Digital goods inventory | commerce.participant.grant_holding |
grantParticipantHolding() from @agentstack/sdk/commerce/participant |
{
"context": { "project_id": 1472 },
"steps": [
{
"action": "buffs.grant_tenant_subscription",
"params": {
"user_id": 12345,
"plan_id": "pro_monthly",
"project_id": 1472,
"verify": true
}
}
]
}Recipe: mcp_tenant_manual_entitlement_grant · Idempotency: webhook uses payment:{payment_id}; shop C24 uses order:{order_id}:{buff_template_id} (shared/mcp/tenant_grant_idempotency.py).
Genes: shared.subscription.two_plane.gen1 · core.commerce.seller_activation.gen1 · core.commerce.assets.presets.gen1