Skip to main content
Managed agents store their configuration in a project and run in MeshAgent’s managed runtime. Their configuration selects models, instructions, tools, and optional service-account credentials. You do not need to host a separate tool server for an embedded Python tool.

Start with a working tool

Save this configuration as agent.yaml. Select a model enabled in your project; the example uses gpt-6.1-sol.
Test the function directly before saving the agent:
The result contains {"total_cents":3000}, captured logs, and an empty list of HTTP requests. This runs the embedded source; it does not ask a model to choose a tool or create an agent. See Python tools for local runner installation and the complete execution contract.

Save the agent and talk to it

In Studio, open your project’s Agents list and select New Agent. Paste the configuration into the YAML editor and select Create. The Edit Agent dialog lets you update an existing agent’s configuration. The CLI’s create and update commands accept JSON, while tools test accepts a YAML file. To use the same file with the CLI, convert it to JSON with a Python environment containing PyYAML:
For an existing agent, use:
Start a conversation with the saved agent:
Use credentials and an API URL for the same environment as your Powerboards or Studio project. A successful local function test does not create the agent or confirm that the deployed service account can access a secret.

What tool calls support

The detailed Python tool reference documents every HTTP argument, response field, schema rule, secret permission, and execution limit. Room-hosted SDK tools are a separate surface described in Tools and Toolkits.

Configure built-in tools and MCP

tools holds embedded Python functions. toolkits enables built-in and provider-hosted capabilities. For example, add this to your agent configuration:
Grok web search accepts at most five domains in either allowed_domains or blocked_domains; it cannot combine both filters in one search toolkit. Use an OpenAI model for this image-generation example. Grok’s native image tool accepts only type: image_generation; it chooses its image model, size, and format. Configuring image settings with Grok returns an explicit error. Secret-backed MCP requests use the agent’s run_as service account and the existing secret proxy permissions. For every provider, set require_approval: never. Managed agents do not yet route interactive MCP approvals. Omitting this setting, selecting always, or adding nonempty always_require_approval returns an explicit error rather than automatically approving calls. Use allowed_tools to limit which tools can run. For OpenAI, MCP preserves custom headers, allowed_tools, never_require_approval, and optional openai_connector_id. A connector ID cannot be combined with use_proxy_secret; proxy secrets require a server URL. Grok MCP supports server URLs, custom headers, allowed_tools, and proxy secrets. It does not support OpenAI connector IDs or per-tool approval settings; these configurations return explicit errors. The managed require_approval: never setting selects calls without interactive approvals and is omitted from the provider request because Grok does not accept that field. An empty allowed_tools list disables the server rather than forwarding Grok’s native empty list, which would enable every tool. Anthropic MCP supports server URLs, allowed_tools, and authentication through use_proxy_secret. An empty allowed_tools list disables all tools on that server. Its native connector does not support custom headers, OpenAI connector IDs; these configurations return explicit errors. Configured toolkits are rebuilt for the selected provider on each turn, including provider changes.

Guardrails

Add guardrails at the top level of the managed-agent configuration, alongside tools, allowed_models, and run_as. Checks use the OpenAI Decisions API through MeshAgent’s metered LLM proxy. Select a Decisions-capable model enabled for your project; replace YOUR_DECISIONS_MODEL below before saving.
Output checks disable live response-text streaming: the complete response is held until approved. A rejected response is discarded. Tool output checks also buffer streamed function results and suppress unchecked tool side events. Neither check can undo a tool’s side effects; protect an HTTP request or write with a tool input check and the appropriate permissions. Output checks inspect the normalized text and structured events delivered to clients. Generated images, audio, and files cannot be inspected by this text-based Decisions integration; they follow the output check’s on_error policy instead of being released as approved media. Input checks likewise reject image, audio, and file attachments through on_error; text checks cannot inspect the media merely from its URL or encoded bytes. Tool matches are exact function names or qualified toolkit.function names. Embedded Python tools use the managed_python toolkit. A configured match that cannot be intercepted by the runtime fails the turn; it is not silently skipped. Provider-hosted tools, including native web search and hosted MCP, do not expose local execution boundaries for these tool checks. Use their allowlists and permissions in addition to conversation checks. Each check requires a unique name, model, instructions, and an explicit minimum_allow_probability from 0 to 1. All checks at a boundary must pass, in configuration order. There can be at most 32 checks across the configuration. on_reject defaults to action: block. on_error defaults to action: fail, which blocks the turn if a check cannot be completed. Set on_error.action: pass to continue past that check when it fails; other configured checks still run. Boundary-specific error actions (block, deny, and replace) are also supported where listed above. A replace action requires a nonempty message. Each rule has max_retries (default 2, allowed 0–3), in addition to the initial attempt. Transport errors, timeouts, HTTP 408/429/5xx responses, and malformed JSON responses are retried with 100, 200, then 400 ms backoff. Each attempt has a 10-second timeout. After retries are exhausted, on_error determines whether the check passes or fails. Policy rejections, refusals, other HTTP errors, and deterministic local validation errors are not retried. Runtime resource limits, including a buffer that was discarded after exceeding its size limit, cannot be bypassed with pass. Decision probabilities are model judgments, not authorization rules: keep deterministic argument validation, identity checks, and spending limits.

Usage and cost

Decisions checks are billable model calls, including checks that reject a request. They use the same proxy and delegated billing context as the managed-agent turn. Usage carries the managed agent’s immutable ID in meshagent.io/agent.id and its name in meshagent.io/agent.name. Guardrail calls additionally carry guardrail.name and guardrail.stage (input, tool_input, tool_output, or output), plus the one-based guardrail.attempt. Retries use the same metered path, so any usage billed by the provider is included in the agent’s totals. In Accounts, use Cost by Managed Agent or LLM Usage by Managed Agent. Select an agent row to see its provider, model, and usage-type breakdown. These reports group by agent ID and include anonymous traffic; they do not depend on a room name or the identity of a user who can view the conversation. Access to cost reports requires billing access, and token reports require usage-report access. Most Active Managed Agents reports runtime minutes. Most Active Managed Agent Users reports LLM tokens grouped by managed agent and the user who sent the turn, including anonymous users. The separate Most Active Room Participants report measures connected minutes in rooms. The managed-agent runtime emits one activity sample per minute while connected; this is not model execution time. Usage recorded before user attribution was available appears as Unknown user in the managed-agent users report. The usage API exposes cost_by_agent, llm_proxy_usage_by_agent, and llm_proxy_usage_by_agent_user. Rows contain agent_id, agent_name, totals, and period_start when an interval is requested. The user report also includes participant_name. Accounts displays the name, while the ID remains available for filtering and drilldowns. To filter another usage report to a managed agent, pass the annotation filter {"meshagent.io/agent.id": "AGENT_ID"}. Resource identity is separate from the charged principal and originating service-account annotations, so delegation does not change which managed agent the report identifies.

How a tool call runs

  1. The model chooses an advertised tool and supplies arguments matching its schema.
  2. MeshAgent validates those arguments and starts a fresh Python invocation.
  3. The function may transform JSON data or await HTTP requests through the host.
  4. Its JSON result returns to the model, which continues the conversation.
Python exceptions, invalid arguments, HTTP transport errors, resource limits, and timeouts fail the tool call. HTTP error responses are available to the function; call response.raise_for_status() to raise for a status of 400 or greater. Worker loss does not automatically replay a call, because an HTTP request may already have changed data. For API-based creation, connection, and access management, see the managed-agent endpoints.

Failure reports

Open Managed agent failures in the Accounts project navigation to inspect managed-agent LLM, tool, and guardrail failures. Project usage-report permission is required. Reports identify the managed agent directly; they do not require access to a user’s thread or attribute the agent to a room. Anonymous use is included. Choose a 1-, 7-, or 30-day window and a category. Issues group the same operation, error classification, HTTP status and stack locations, with first/last occurrence and counts. Select an issue for its occurrence history. Hourly activity distinguishes failed operations, retry attempts, policy rejections, recovery, and checks that passed because on_error.action is pass. Counts are diagnostic events, not unique conversations or affected users. Python diagnostics retain the exception class and ordered source line/column positions. LLM diagnostics retain recognized provider error codes and HTTP status. Guardrail diagnostics identify the boundary and rule, HTTP status when available, attempt number and outcome. An occurrence also includes its event ID and runtime session ID. These reports do not include thread contents. Secrets are excluded before diagnostic data is queued. Exception messages, source-code previews, local variables, filenames, provider bodies, request/response headers and tool arguments are not recorded. Unrecognized errors become OperationError; reports never fall back to displaying an unchecked error string. This also protects unknown or encoded credentials that pattern-based redaction could miss. Use the exception class and line/column to inspect your own tool source. The API is GET /accounts/projects/{project_id}/agents/failures, with start, end (an exclusive bound, at most 31 days), optional agent, category, fingerprint, and offset. It returns up to 100 issue groups, hourly trends, up to 100 events, and has_more. Event history is retained for 90 days. Publishing is asynchronous and bounded; a full queue or unavailable telemetry backend can lose diagnostic events. Reports are not a billing ledger or an audit-log guarantee. Self-hosted deployments must apply meshagent-server/sql/clickhouse/add_managed_agent_failures.sql before deploying the updated observability exporter, and configure the managed-agent usage Pub/Sub topic and credentials. The same existing usage pipeline transports failure events.