Bots
Bots
A bot is a saved workflow that runs a One Agent loop on a clock, answers messages, keeps its own memory and files, and stays inside a policy you set.
A bot is a saved workflow with kind: bot. Its one task is a One Agent loop with a mission. It is not a separate runtime: what makes it a bot is the wiring around the YAML, which is where the schedule, the chats, the triggers, the policy and the budget live.
| A bot has | Set by | Page |
|---|---|---|
| A mission and a tool fence | The YAML | Playbook reference |
| A clock | schedule tool, a schedule on the bot | Schedules and wake |
| Teammates | peers, bot groups, A2A | Bot to bot and groups |
| Chats and a web widget | Pairing and bindings | Channels and voice |
| Rules and a spend cap | Stored presets, locks, budgets | Permissions and budget |
| Files, an inbox and memory | workspace, memory | Workspace and inbox |
| Outside events | Webhook, email, Slack, Gmail, Git | Triggers and hooks |
| A control surface on every door | REST, MCP, CLI | REST, MCP and CLI |
A minimal bot
workflow:
name: Competitor Watch
description: Checks a page for pricing changes
tasks:
- type: harness
id: watch
agent: one-agent
goal: "Check {input} for pricing changes"
max_iterations: 8
allowed_tools: [web_search, web_fetch, task_complete]
mission: |
You are Competitor Watch. Reply NO-CHANGE when nothing changed.
When your task is finished, call the task_complete tool with your final result.Save it as a bot over REST:
curl -s -X POST https://api.plungeai.com/v1/workflows \
-H "Authorization: Bearer $PLUNGE_API_KEY" -H 'Content-Type: application/json' \
-d '{"name":"Competitor Watch","kind":"bot","yaml":"workflow:\n name: Competitor Watch\n tasks:\n - type: harness\n id: watch\n agent: one-agent\n goal: \"Check {input} for pricing changes\"\n allowed_tools: [web_search, web_fetch, task_complete]\n mission: |\n You are Competitor Watch. Reply NO-CHANGE when nothing changed.\n When your task is finished, call the task_complete tool with your final result.\n"}'In Studio, choose New, then Bot agent; the bot opens in the same YAML editor as a flow. The bot templates (GET /v1/templates?kind=bot) are ready-made starting points; POST /v1/templates/{id}/use copies one into your account.
What a save checks
Saving runs the CNL schema and then the kind lint, before anything is written. A refusal is 422 invalid_workflow with errors and warnings, and the stored row is unchanged.
- A bot is exactly one task, and it is
type: harness. - A declared
allowed_toolsfence must includetask_complete. A mission that never mentionstask_completeis a warning. memory_owneris refused: a bot's memory tenant comes from the user who runs it.- A local bot (
local: trueorlocal_agents) should setagent: one-agent.harness-agentandagentic-agentare still accepted until the switch-over;universal-agentnever is. posture,peers,review,max_runtime_sandworkspaceapply only onagent: one-agent. Onharness-agent,agentic-agentoruniversal-agentthey are an error, because those runtimes would ignore them.- A hard-coded email address or UUID in the YAML is a warning.
Identity and who may use what
When a saved bot runs, the engine tells the loop which bot it is (bot_id) and who owns it (bot_owner). The inbox, the schedule and message_bot tools, the browser bot session and the persistent workspace need that identity.
- These abilities belong to the owner. A teammate who runs a shared bot runs it without an identity.
- A saved workflow that is not a bot but uses
agent: one-agent, run by its owner, is treated like a bot. - Deleting a bot deletes its scheduled jobs and wipes its own memory namespace (the one a web widget uses). What the bot saved with
memorywhile you ran it lives in your own memory and stays; remove it withPOST /v1/memory/forget.
Every run uses the stored policy
The engine loads the bot's stored policy once per run, on every door: a run by id, a schedule, a trigger, a chat message, MCP and Studio all stop at the same caps and holds. See Permissions and budget.