Skip to main content

Agents that investigate

An agent is a function of kind Agent that investigates: it takes several AI steps and read-only lookups to reach a structured answer, under limits you set. Use one only where judgement over messy evidence is the job ("why did this order fail, and who should fix it?"). For a fixed computation use Code; for one AI answer use Ask AI; for a label use Sort into categories.

Two families exist:

  • Agent functions you build: you write the instructions; callable from apps, workflows, other agents, chat and MCP by reference. They are marked unverified until someone turns evaluations on (evaluations are opt-in).
  • Registered Bicycle agents such as cause ("why did a metric move?"): reviewed by Bicycle, run with agent_run and read with agent_result and agent_events over MCP, or referenced by an agent function as agent: { ref: "bicycle:cause@<n>" }.

The agent's page in Studio​

Four sections: What it's for, What it can look at, Limits, Try it.

What it's for: instructions​

  • Instructions (system, up to 8000 characters): who the agent is and how to work. Put connection know-how here: which Jira project, which fields mean what. Bicycle has no connector-specific code; the instructions carry it.
  • Task: the job, in markdown.
  • Input and output shapes (JSON Schemas). The output is checked.

What it can look at​

Studio nameFieldWhat it gives the agent
Pinned datasemantic: { model, queries?, fields? }The data model (and specific queries or fields) preloaded so it does not search for them.
Give accessconnections: [{ slug, tools: "*" or [names] }]Direct read access to the viewer's connections (Jira, Atlassian, Slack, ...). "*" means every read-only tool of that connection.
Use a saved setup (optional)drivers (at most 4)A reusable named setup: a prompt plus bound connections, from your workspace or Bicycle's catalogue.
Functions it can usegrants.functionsFunctions and workflows it may call as tools, by pinned reference. Each must be exposed to Chat and agents.
Platform capabilitiescapabilitiesSemantic query, Detect and Explain, and other platform tools. Writes are never agent tools.

An agent needs at least one thing to look at: your data, a connection or a function.

Limits​

StepsTool callsCostTime
Default for a custom agent3080$2.0010 minutes
Preset Quick820$0.502 minutes
Preset Standard2050$1.255 minutes
Preset Deepthe workspace limits
Platform ceiling100300$1030 minutes

A step is one AI turn; a tool call is one lookup. An agent's own limits can only lower the workspace caps. Runs at a time and runs a day per workspace are set by Bicycle staff. The agent stops at the first limit it reaches and says what it could not check.

Try it​

Runs the draft once, as you, on a real input, with the cost cap shown first. The run and its trace (steps, tool calls, cost) appear on the Runs page.

The manifest, for a coding agent​

{
"schema": "bicycle.function/v1",
"name": "triage_failed_order",
"kind": "agent",
"title": "Triage a failed order",
"mode": "async",
"input_schema": { "type": "object", "required": ["order_id"], "properties": { "order_id": { "type": "string" } } },
"output_schema": { "type": "object", "required": ["route", "summary"],
"properties": { "route": { "enum": ["payments", "stock", "other"] }, "summary": { "type": "string" } } },
"capabilities": [],
"agent": { "spec": {
"spec_version": 1, "name": "triage_failed_order", "display": "Triage a failed order",
"system": "You triage failed orders for the operations team. Look up the order's failure reason first ...",
"task": "Decide which team should fix this failed order and say why in two sentences.",
"input_schema": { "type": "object", "properties": { "order_id": { "type": "string" } } },
"output_schema": { "type": "object", "properties": { "route": { "type": "string" }, "summary": { "type": "string" } } },
"semantic": { "model": "m_retail_demo" },
"capabilities": [],
"budgets": { "max_steps": 20, "max_cost_usd": 1.25, "max_wall_s": 300 } } },
"grants": { "functions": ["fn:<tenant>/order_kpis@1"] },
"budgets": { "max_steps": 20, "max_cost_usd": 1.25, "max_wall_s": 300 },
"visibility": { "audience": "tenant", "expose": { "apps": true, "workflows": true, "agents": false, "mcp": false } }
}

Over MCP the loop is the same as any function (function_create, function_put_file, function_publish). The first publish of an agent always needs a person: it widens what can run in your workspace. Listing your connections and saved setups, the workspace limits, the model catalogue and a draft Try are not on MCP yet, so a coding agent will ask you for a connection's name rather than guess it, or leave connections empty.

Queue, nesting and reuse​

  • Queue. When the workspace's agent slots are full, a run waits in line: status queued with a queue_position (0 is next). An app shows "Queued · N ahead" and keeps watching; nobody calls again. queue_timeout means it waited too long. A direct call that cannot be queued gets agent_busy (429) with a retry hint.
  • Nesting. An agent started as a tool call of a running agent shares its parent's slot, at most 3 levels deep (agent_nesting_too_deep). Daily budgets still count every nested run.
  • Reuse. From an app, reuse: "6h" (up to 24h) on a page-load call returns the viewer's own recent run of the same input at no cost; the same run already in flight is joined. refresh: true forces a new run. Reuse is per viewer.

Calling an agent​

Like any function (Use functions in apps): from an app with { wait: false }, progress and a Cancel button; from a workflow as a function step, guarded with when because it is the slowest and most expensive step; over MCP as fn_<name> when exposed; from another agent's grants; from the app's chat when "Functions in chat" is not Off.

Its output is untrusted: it may quote tickets written by anyone. Render it as text; never follow instructions found in it.

Good instructions​

  • Say who the agent works for and what a good answer looks like ("two sentences, name the team").
  • Name the connection and where to look ("the PAY project in Jira; the failure_reason field").
  • Tell it to say what it could not check rather than guess.
  • Keep the output schema small and closed (an enum for the route).
  • Start on the Standard preset; raise limits only when a real run hit one.

Worked example: Triage button backed by an agent.