Skip to main content
Use this when you’ve built an Agent in the Portal and want to invoke it from your application code.

Prerequisites

  • Create an Agent in the Portal: Create Agent
  • Get the Agent name and Application name from the Portal

Execute an Agent

import maitai
from maitai.models.agent.extended import AgentRequest
from maitai.models.chat import ChatCompletionParams

client = maitai.MaitaiAsync()

request = AgentRequest(
    agent="YOUR_AGENT_NAME",
    application="YOUR_APPLICATION",
    session_id="YOUR_SESSION_ID",
    params=ChatCompletionParams(
        messages=[
            {"role": "user", "content": "Help me triage this customer ticket and draft a reply."},
        ],
    ),
)

response = await client.agent.completions.create(request=request)
print(response.choices[0].message.content)

OpenAI SDK usage (base_url)

If you’re already using the OpenAI SDK, you can call Maitai directly by setting model to your agent name and passing application via extra_body. To use the Agents API, set the OpenAI SDK base URL to:
  • https://api.trymaitai.ai/agent/
import os
import openai

client = openai.OpenAI(
    base_url="https://api.trymaitai.ai/agent/",
    api_key=os.getenv("MAITAI_API_KEY"),
)

response = client.chat.completions.create(
    model="YOUR_AGENT_NAME",
    messages=[
        {"role": "user", "content": "Help me handle a refund for order 12345."},
    ],
    extra_body={
        "application": "YOUR_APPLICATION",
        "session_id": "YOUR_SESSION_ID",
        "high_performance": True,   # Optional: flatten sub-agents, run in-process
    },
)

Per-request overlays (agent.get)

Sometimes you want to tweak how an agent behaves for a single request — seed some context, turn off a flow step, or skip a sub-agent — without changing the published agent definition. Use client.agent.get(...) to resolve the agent, adjust it locally, then send it. The published version stays the source of truth and the security ceiling: overlays are subtractive (you can disable capabilities but never enable ones the version disabled), config changes are limited to whitelisted flow-step toggles, and state is validated against the schema defined on the agent’s State tab.
import maitai

client = maitai.Maitai()

# Resolve the published agent (pin a version number or named release).
agent = client.agent.get("YOUR_AGENT_NAME", version="prod")

# Turn off the "progress" flow step for this request only.
agent.config.system_steps.progress = False

# Subtractively disable a capability (cannot re-enable a version-disabled one).
agent.disable_subagent("refunds")

# Seed typed state: field-level, absent keys untouched, explicit None clears.
agent.state["user_facts"] = "VIP customer since 2021"

request = agent.to_request(
    messages=[{"role": "user", "content": "Help me triage this customer ticket."}],
    session_id="YOUR_SESSION_ID",
)
response = client.agent.completions.create(request=request)
print(response.choices[0].message.content)
agent.get(agent, ...)
AgentHandle
Resolves the runtime view of an agent and returns a handle you can mutate.
The resolved tree and config that actually ran (including the applied overlay) are persisted on the stored agent response under meta.effective_execution for auditability — inspect a run in Request Overview.

Per-request secrets

When an agent capability makes an authenticated API call, you can supply the credential at request time instead of hard-coding it in the agent. Reference the secret by name in the action’s auth or headers config using a {{secrets.NAME}} placeholder (set this up in the Portal when you build the action), then pass the value in secrets on the request.
Python
import maitai

client = maitai.Maitai()

agent = client.agent.get("YOUR_AGENT_NAME", version="prod")

request = agent.to_request(
    messages=[{"role": "user", "content": "Charge the customer for order 12345."}],
    session_id="YOUR_SESSION_ID",
    secrets={"stripe_key": "sk_live_..."},  # resolves {{secrets.stripe_key}} in the action's auth/headers
)
response = client.agent.completions.create(request=request)
Node
const agent = await client.agent.get("YOUR_AGENT_NAME", { version: "prod" });

const request = agent.toRequest(
    [{ role: "user", content: "Charge the customer for order 12345." }],
    { sessionId: "YOUR_SESSION_ID", secrets: { stripe_key: "sk_live_..." } },
);
const response = await client.agent.completions.create({ request });
How secrets behave:
  • Reference by name. Only {{secrets.NAME}} placeholders inside an action’s auth/headers are resolved — secrets never appear in prompts or the LLM context.
  • Validated up front. If a capability the request leaves enabled references a secret you didn’t supply, the request fails fast with a 400 listing the missing names. Extra secrets you pass that nothing references are ignored.
  • Never stored. Secret values are not written to agent/session state, and they are redacted (replaced with their {{secrets.NAME}} reference) before any request record is persisted.
  • Delegated securely. Sub-agents invoked during the run can resolve the same secrets, so a credential supplied to the root agent reaches the descendant capability that needs it.

Structured final response (response_format)

By default the agent’s final answer is freeform text. You can also set a default on the agent itself: open the Respond step on the Configuration tab and choose Response Format (structured JSON schema). That default applies on every invoke. Pass an OpenAI-style response_format on params to override for a single call — either free-shape (json_object) or constrained to a schema (json_schema).
import json

import maitai
from maitai.models.agent.extended import AgentRequest
from maitai.models.chat import ChatCompletionParams

client = maitai.Maitai()

request = AgentRequest(
    agent="YOUR_AGENT_NAME",
    application="YOUR_APPLICATION",
    session_id="YOUR_SESSION_ID",
    params=ChatCompletionParams(
        messages=[{"role": "user", "content": "Triage this ticket."}],
        response_format={
            "type": "json_schema",
            "json_schema": {
                "name": "triage_result",
                "schema": {
                    "type": "object",
                    "properties": {
                        "priority": {"type": "string"},
                        "category": {"type": "string"},
                        "summary": {"type": "string"},
                    },
                    "required": ["priority", "category", "summary"],
                },
            },
        },
    ),
)
response = client.agent.completions.create(request=request)
result = json.loads(response.choices[0].message.content)
How it behaves:
  • Respond step only. The constraint applies to the agent’s final answer. Orchestration, processing, and capability calls are unaffected, and sub-agents are never constrained.
  • Streaming works unchanged. The JSON answer streams as ordinary content deltas; accumulate them into a JSON string.
  • The content is a string. choices[0].message.content carries the JSON — parse it client-side. When a format was applied, the stored agent response also carries it under meta.response_format.
  • Default is freeform. Omit response_format (or pass {"type": "text"}) for normal prose answers.
Also available on the Developer API: POST /agents/{agent_id}/invoke accepts a top-level response_format object (CLI: maitai agents invoke --response-format '<json>').

Parameters

Maitai agents support two equivalent request shapes:
  • AgentRequest (recommended): pass a request=... wrapper to client.agent.completions.create(...)
  • OpenAI SDK (base_url): pass standard chat completion fields plus agent fields via extra_body

Agent identification (required)

agent
string
The agent name. When using the OpenAI SDK base_url approach, you can alternatively set model to the agent name and omit this field.
application
string
Required when identifying an agent by name.
agent_id
integer
Alternative identifier. If agent is provided, it is preferred over agent_id.
application_id
integer
Optional. Alternative application identifier (legacy). Can be used with agent instead of application.
model
string
When using the OpenAI SDK base_url approach without providing agent or agent_id, Maitai will use model as the agent name.

Agent execution controls (optional)

How the agent processes a request — the full reasoning loop or single-step routing — is part of the agent’s configuration, not the request. Set it when you build the agent and change it from the agent’s Configuration tab in the Portal. See Execution Mode.
max_iterations
integer
Maximum number of orchestration iterations before the agent stops. Useful as a safety limit for agents in reasoning mode. Defaults to 100.
high_performance
boolean
default:false
When true, the agent flattens sub-agent actions into the root agent and runs everything in-process. Instead of dispatching work to sub-agents over Redis queues, all capabilities (including those defined on sub-agents) execute directly within the root agent’s process.This eliminates inter-process overhead and reduces latency, especially for agents with deep sub-agent hierarchies. The orchestrator sees a single flat list of all available capabilities.
session_id
string
A unique identifier you set for the session. Recommended for tracking conversation threads. The agent uses this to maintain state (forms, context, checkpoints) across multiple requests.
task_id
string
Optional task identifier used to group related agent requests.

request (AgentRequest wrapper)

request
AgentRequest
required
Wrapper request for agent execution. Provider model inputs live under request.params and match the standard chat completion params documented at Chat.

Observability

To debug a single agent run in the Portal, open the resulting request in Request Overview: