Skip to content

Configuration Reference

Every field IntaGrin recognizes in ai.yaml, grouped by section (one per config model), generated directly from the Pydantic schema in src/intagrin/config/schema.py.

This file is generated by scripts/generate_config_reference.py — do not hand-edit it. A missing description means the schema field itself needs one, not this file.

AppConfig below is the root of ai.yaml; every other section is a nested config block referenced from it or from another section.

AppConfig

FieldTypeDefaultDescription
versionstringrequiredai.yaml schema/format version.
namestringrequiredProject name.
descriptionstring | nullNoneShort human-readable summary of what this app does.
state_schemastring | nullNoneGlobal JSON schema module path for Typed Shared State
max_session_budget_usdnumber | nullNoneGlobal hard cost ceiling per session
importslist[ImportConfig][]Other ai.yaml-shaped files to merge into this one.
circuit_breakersCircuitBreakersConfig(factory default)Thresholds that halt a runaway session — handoff loops, tool failure streaks, USD cost, delegation depth.
modelModelConfigrequiredDefault LLM configuration, used by any agent that doesn't set model_override.
memoryMemoryConfigrequiredConversation history backend used by all agents in this app.
ragRAGConfig | nullNoneVector retrieval configuration — when set, auto-registers a search_knowledge_base tool.
episodic_memoryEpisodicMemoryConfig | nullNoneDiscrete, structured, individually queryable event records (e.g. "user prefers window seats", "booking BK-4471 failed: card declined") — distinct from the single blended long_term_memory prose summary and from rag's document/knowledge-base retrieval. When set, auto-registers remember_episode/recall_episodes tools. Stored in a sqlite/postgres episodes table (memory.type must be 'sqlite' or 'postgres' — same scope as shared_memory/run_logs); a no-op elsewhere.
toolslist[LocalToolConfig | MCPToolConfig | OpenAPIToolConfig | SandboxToolConfig][]Tools declared at the root level, available to be referenced by name from any agent.
agentsdict[str, AgentConfig]{}The agents that make up this app, keyed by name.
routersdict[str, RootRouterConfig]{}Root-level deterministic routers, keyed by name — evaluated before any agent runs.
workflowsdict[str, list[WorkflowTask]]{}Named multi-step task sequences, run via inta run <workflow> rather than conversationally.
reducerslist[StateReducerConfig][]How concurrent writes to shared state keys are combined.
condition_functionslist[ConditionFunctionConfig][]Named, pure Python predicate functions that routers[].condition and tools[].available_when expressions may call by name (e.g. is_eligible(customer_tier)), for branching logic the restricted condition grammar's bare comparisons/and/or/not can't express on their own — without forcing an LLM handoff just to make a deterministic decision.
telemetrylist["langfuse" | "otel"][]Tracing backends to export spans to.
serverServerConfig(factory default)inta serve/inta monitor configuration — auth, webhooks.
default_agentstringrequiredAgent that receives the first message in a new session.

AgentConfig

FieldTypeDefaultDescription
descriptionstring | nullNoneShort human-readable summary of this agent's purpose — shown in the Monitor dashboard graph.
model_overridestring | nullNoneUse a different LiteLLM model for this agent instead of the app-level model.primary.
system_prompt_filestring | nullNonePath to a Jinja2 template file rendered as this agent's system prompt.
system_prompt_langfusestring | nullNoneLangfuse prompt name to fetch as this agent's system prompt instead of a local file.
system_prompt_modulestring | nullNonePython module path exposing a function that returns this agent's system prompt dynamically.
prompt_keystring | nullNoneKey used to look up this agent's prompt when multiple agents share a prompt source.
required_scopeslist[string][]Scopes/permissions a caller must have (checked against session state) before this agent can run.
response_schemastring | nullNoneDotted path to a Pydantic model this agent's final response is validated against; a corrector model retries once on violation.
auto_routebooleanFalseEnable semantic swarm routing (LLM-Bypass Group Chat)
lazy_load_toolsbooleanFalseEnable semantic tool retrieval to reduce context window bloat
toolslist[LocalToolConfig | MCPToolConfig | OpenAPIToolConfig | SandboxToolConfig | ToolReferenceConfig][]Tools available to this agent — local Python functions, MCP servers, OpenAPI wrappers, or references to root-level tools.
handoffslist[string][]Agent names this agent may conversationally transfer control to (compiled to a transfer_agent tool).
delegationslist[string][]Agent names this agent may delegate a sub-task to. Compiles two tools: delegate_task (one sub-task, one isolated child engine — the delegating agent's own turn is never interrupted) and delegate_to_many (fan out N concurrent instances of the same sub-agent, one per instruction, for an item count only known at runtime — capped by circuit_breakers.max_parallel_fan_out).
routerslist[RouterConfig][]Deterministic Python conditions checked before the LLM runs, to bypass it entirely when they fire.
spawnsAgentSpawningConfig | nullNoneEnables dynamic runtime agent creation: this agent gets a spawn_agent tool that creates a narrowly-scoped sub-agent (new system prompt, a subset of spawns.tool_pool, an inherited model) mid-session, runs it to completion in an isolated child engine, and returns the result as an ordinary tool result — it does not transfer control, so the creator's own turn is never interrupted and concurrent spawn_agent calls in one turn have nothing shared to race on. None (default) means this agent cannot spawn anything — today's behavior.

AgentSpawningConfig

FieldTypeDefaultDescription
tool_poollist[string]requiredClosed allow-list of already-declared tool names a dynamically-created sub-agent's tools are drawn from — never a new tool implementation supplied at runtime. Must be a subset of this agent's own tools: (enforced at parse time); an agent can only hand off capabilities it already has, never escalate through creation. The literal string "*" is shorthand for every tool this agent itself has — expanded to that concrete list at parse time (AgentConfig's own subset validator), so it still can never grant more than the agent already holds.
model_poollist[string] | nullNoneLiteLLM model identifiers a spawned agent may be assigned. None (default) means every spawned agent inherits the spawning agent's own resolved model — the spawning LLM never picks a model tier itself unless this is explicitly set.
max_creations_per_sessioninteger3Session-wide cap on how many agents this agent may dynamically create.
requires_approval_on_first_actionbooleanTrueGate a spawned agent's very first tool call behind human approval (reuses the existing requires_approval/multi-approver /resume mechanism), regardless of whether that specific tool is itself approval-gated. Safe-by-default: opt out, not opt in.
allow_recursive_spawningbooleanFalseWhether an agent spawned by this factory may itself spawn further agents (same tool_pool — no privilege growth), up to max_spawn_depth. Off by default.
max_spawn_depthinteger1Max recursive spawn depth, only consulted when allow_recursive_spawning is true.
result_schemastring | nullNoneDotted path to a Pydantic model a spawned agent's return_to_creator call must conform to. When set, return_to_creator's tool schema is derived from this model instead of a generic free-text summary field — steering the model via constrained tool-call decoding rather than just asking nicely — and the arguments are re-validated server-side before being accepted, self-healed via the same corrector-model retry already used for malformed tool arguments elsewhere. None (default) keeps today's free-text summary behavior.
on_completelist[StateWriteAction][]State writes applied automatically once a spawned agent genuinely completes — return_to_creator or a final text response, never on a pause awaiting approval, never on a forced max-turns abort. Runs through the exact same reducer/state_schema pipeline as write_state, so validation and merge strategies apply identically — this is not a second, less-validated write path. Lets a tools[].available_when gate (or any other state-driven condition) unlock declaratively, instead of requiring the spawned agent's own instruction text to call write_state on the framework's behalf.

AuthConfig

FieldTypeDefaultDescription
type"api_key" | "custom" | "none"'none'Authentication mode for inta serve/inta monitor: 'none' (no auth), 'api_key' (a single shared secret — sent as an Authorization: Bearer token for inta serve's API, or as the password in HTTP Basic auth for inta monitor's dashboard; the Basic auth username is not checked and can be any value, e.g. 'admin'), or 'custom' (delegates to a project-supplied verify_token function).
env_varstring | null'INTAGRIN_API_KEY'Environment variable holding the API key, when type is 'api_key'. The server reads this at each auth check — export it before starting the server.
custom_modulestring | nullNonePython module path (e.g. 'auth.custom') exposing verify_token(token: str) -> bool | str, when type is 'custom'. Must return the tenant id as a string for per-tenant session isolation — any other truthy value is rejected (401), not silently treated as a single shared tenant.
approver_env_varstring | nullNoneEnvironment variable holding a separate secret required (via the X-Approver-Key header) to approve a requires_approval tool call through /resume. Without this, the same credential that triggered the gated call can immediately approve it — set this to require a distinct reviewer credential from the requester's own session auth. Acts as the single default approver (id 'default') when approvers isn't set.
approversdict[str, string] | nullNoneNamed approvers for multi-approver chains: maps an approver id (e.g. 'finance', 'security') to the environment variable holding that approver's own X-Approver-Key secret. A tool's required_approvers list names which of these ids must each sign off via /resume before it executes. Independent of approver_env_var — set both to keep a single default approver alongside named ones.

CircuitBreakersConfig

FieldTypeDefaultDescription
max_handoffs_per_sessioninteger | null25Max allowed handoffs per session to prevent infinite loops
max_tool_failures_in_a_rowinteger | null3Max sequential tool failures before halting
max_usd_cost_per_sessionnumber | nullNoneMax USD cost per session before halting
max_delegation_depthinteger3Max nested sub-agent delegation depth before rejecting further delegation
max_delegation_turnsinteger15Max turns a delegated sub-agent may take before it is forcefully aborted
max_parallel_fan_outinteger10Max instructions a single delegate_to_many call may fan out to concurrently — each one runs a full isolated sub-agent to completion, so an LLM-chosen item count with no ceiling could spawn an unbounded number of child engines/LLM calls at once. A call over this limit is rejected outright (asking the caller to split the work into smaller batches) rather than silently truncated.
max_parallel_tool_calls_per_turninteger10Max ordinary (non-transfer) tool calls a single LLM completion may request that actually get executed concurrently in one turn. A model can request an arbitrary number of tool calls in one completion with no natural ceiling; calls beyond this limit are not executed — each gets a synthetic tool-result telling the model to split the work across turns — rather than silently gathered anyway, mirroring how a duplicate control-transfer call in the same turn is rejected rather than run.
max_corrector_tokensinteger1000max_tokens applied to every self-healing corrector-model call — both malformed tool-call argument repair and response_schema/result_schema repair. These calls previously had no max_tokens set at all, making their cost genuinely unbounded; capping the output side bounds each individual corrector call's worst-case cost.
max_compression_batch_messagesinteger50Max messages folded into long_term_memory per memory-compression LLM call. When more messages than this are evicted from the context window at once, compression runs in successive batches of this size, each folded into the summary in turn, instead of dumping an unbounded amount of evicted conversation into a single corrector-model prompt (the summary's own output side was already capped at 500 tokens; this bounds the input side).

ConditionFunctionConfig

FieldTypeDefaultDescription
namestringrequiredName a routers[].condition or tools[].available_when expression can call, e.g. is_eligible(customer_tier, order_total). Must match the Python function name.
modulestringrequiredPython module path (e.g. 'tools.condition_functions') containing a pure, side-effect-free function named name that takes plain values and returns bool. Called with already-evaluated bare state-key names/literals as positional arguments — the function itself is never parsed as part of the condition grammar, only invoked by name, so this is the one way to express branching logic that the restricted condition grammar's comparisons/and/or/not can't reach (e.g. a regex match or a multi-field business rule) without falling back to an LLM handoff.

EpisodicMemoryConfig

FieldTypeDefaultDescription
embedding_modelstring'text-embedding-3-small'Embedding model used to vectorize episode content and recall_episodes queries for semantic search. Defaults to match rag.embedding_model's default so a project using both features doesn't need two different embedding providers configured.
scope"session" | "tenant" | "global"'session'Visibility scope for recorded episodes, independent of memory.shared_scope (a project may want the long_term_memory summary private per-session while episodic events are shared globally, or vice versa). 'session': only this session_id's own episodes. 'tenant': every session under the same authenticated caller/tenant prefix (same convention as memory.shared_scope: tenant). 'global': every session in the project, any tenant.
default_limitinteger5Default number of episodes recall_episodes returns when the caller doesn't pass an explicit limit.

GuardrailsConfig

FieldTypeDefaultDescription
banned_wordslist[string][]Words/phrases that, if present in a user message or model output, are blocked before reaching the LLM or the user.
mask_piibooleanFalseRedact common PII patterns (emails, SSNs, card numbers) from messages before they're sent to the LLM or logged.
system_safeguardsbooleanFalseAppend a built-in safety instruction to the system prompt discouraging harmful/off-policy behavior.
custom_modulestring | nullNonePython module path exposing a custom guardrail check function, run in addition to the built-in checks above.

ImportConfig

FieldTypeDefaultDescription
pathstringrequiredPath to another ai.yaml-shaped file to merge in (agents, tools, workflows, reducers).
namespacestring | nullNonePrefix added to imported agent/workflow names, to avoid collisions with the importing project.

LocalToolConfig

FieldTypeDefaultDescription
namestringrequiredTool name exposed to the LLM for tool-calling — must match the Python function name.
modulestringrequiredPython module path (e.g. 'tools.custom_tools') containing the function named name.
requires_approvalbooleanFalseRequire human-in-the-loop approval before this tool actually executes.
required_approvalsinteger1Number of distinct approvers (see server.auth.approvers) who must each approve via /resume before this tool executes — 1 (default) matches today's single-approval behavior. Ignored unless requires_approval is true.
required_approverslist[string] | nullNoneSpecific approver ids (keys of server.auth.approvers) that must each sign off, instead of any required_approvals approvers. Ignored unless requires_approval is true; when set, overrides required_approvals with len(required_approvers).
available_whenstring | nullNoneState condition (same restricted grammar as routers[].condition — bare state-key names, comparisons, and/or/not; no method calls or attribute access) gating whether this tool is even offered to the agent this turn. Unlike a prompt instruction asking the model not to call a tool yet, the tool is structurally absent from its schema until the condition is true — re-checked server-side on every call regardless, the same defense-in-depth already applied to tool_pool and every other schema-driven gate in this codebase. None (default) means always available, today's behavior.
untrusted_outputbooleanFalseMark this tool's return value as untrusted (may contain LLM-directed instructions injected by a third party — the 'lethal trifecta' pattern: untrusted content + access to private data/state + a way to exfiltrate). False by default for local tools, since they're developer-authored Python — set true for one that fetches external content (e.g. a web scraper). The moment any tool call with untrusted_output=true succeeds, state['_untrusted_content_ingested'] is set true for the rest of the session; reference it from another tool's available_when (e.g. 'not _untrusted_content_ingested') to withhold a sensitive tool once this session has seen untrusted content, or from a router condition to force a review handoff.

MCPToolConfig

FieldTypeDefaultDescription
namestringrequiredTool name exposed to the LLM for tool-calling.
typestringrequiredDiscriminator — must be the literal string 'mcp'.
commandstringrequiredExecutable used to launch the MCP server subprocess (e.g. 'npx').
argslist[string]requiredArguments passed to command when launching the MCP server.
requires_approvalbooleanFalseRequire human-in-the-loop approval before this tool actually executes.
required_approvalsinteger1Number of distinct approvers (see server.auth.approvers) who must each approve via /resume before this tool executes — 1 (default) matches today's single-approval behavior. Ignored unless requires_approval is true.
required_approverslist[string] | nullNoneSpecific approver ids (keys of server.auth.approvers) that must each sign off, instead of any required_approvals approvers. Ignored unless requires_approval is true; when set, overrides required_approvals with len(required_approvers).
available_whenstring | nullNoneState condition (same restricted grammar as routers[].condition) gating whether this tool is even offered to the agent this turn — see LocalToolConfig.available_when for the full explanation. None (default) means always available, today's behavior.
untrusted_outputbooleanTrueMark this tool's return value as untrusted — see LocalToolConfig.untrusted_output for the full explanation. True by default for MCP tools, since they reach an external server outside the project's own trust boundary; set false only for an MCP server you fully control and trust.

MemoryConfig

FieldTypeDefaultDescription
type"sliding_window" | "buffer" | "sqlite" | "postgres" | "redis" | "custom"'sliding_window'Conversation history backend: 'sliding_window'/'buffer' (in-process, lost on restart), 'sqlite' (local file), 'postgres', 'redis', or 'custom'.
max_messagesinteger20Number of most-recent messages kept in context for sliding_window/buffer memory.
db_pathstring | null'.ai/memory.db'SQLite database file path, relative to the project root, when type is 'sqlite'.
connection_urlstring | nullNoneDirect connection URL for postgres/redis, e.g. 'postgresql://...' or 'redis://...'. Takes precedence over env_var.
env_varstring | nullNoneEnvironment variable holding the connection URL for postgres/redis (e.g. 'DATABASE_URL', 'REDIS_URL'), used if connection_url isn't set directly.
custom_modulestring | nullNonePython module path exposing a CustomCheckpointer class, when type is 'custom'.
shared_scope"session" | "tenant" | "global"'session'Scope for the long_term_memory summary _compress_memory produces: 'session' (default — today's behavior, private to one session_id), 'tenant' (shared across every session under the same authenticated caller/tenant), or 'global' (shared across every session in the project, any tenant). Persisted to a new shared_memory table (sqlite/postgres only, same scope as run_logs) and merged into a session's long_term_memory on initialize(). Last-write-wins across concurrent sessions writing the same scope — no merge/versioning.

ModelConfig

FieldTypeDefaultDescription
primarystringrequiredLiteLLM model identifier used for this agent/app (e.g. 'openai/gpt-4o-mini', 'anthropic/claude-3-5-sonnet'). Required.
fallbackstring | nullNoneModel to retry with if the primary model call fails (rate limit, outage, etc.).
variantslist[ModelVariantConfig] | nullNoneA/B or canary model routing: split traffic across weighted model variants instead of always using primary. Assignment is deterministic per session_id (sticky for the whole conversation, never flips mid-session) via a weighted hash. None (default) means every session uses primary, exactly today's behavior.
temperaturenumber0.2Sampling temperature passed to the LLM, 0.0 (deterministic) to 2.0 (most random).
max_tokensinteger1500Maximum tokens the LLM may generate in a single completion.
use_cachebooleanFalseEnable semantic caching to save API costs
guardrailsGuardrailsConfig(factory default)Content-safety checks applied to this model's inputs/outputs.

ModelVariantConfig

FieldTypeDefaultDescription
modelstringrequiredLiteLLM model identifier for this variant.
weightnumberrequiredRelative weight for traffic splitting — weights don't need to sum to 1.

OpenAPIToolConfig

FieldTypeDefaultDescription
namestringrequiredTool name exposed to the LLM for tool-calling.
typestringrequiredDiscriminator — must be the literal string 'openapi'.
urlstringrequiredURL of the OpenAPI/Swagger spec IntaGrin generates a tool wrapper from.
auth_envstring | nullNoneEnvironment variable holding a bearer token/API key sent with requests to this API.
requires_approvalbooleanFalseRequire human-in-the-loop approval before this tool actually executes.
required_approvalsinteger1Number of distinct approvers (see server.auth.approvers) who must each approve via /resume before this tool executes — 1 (default) matches today's single-approval behavior. Ignored unless requires_approval is true.
required_approverslist[string] | nullNoneSpecific approver ids (keys of server.auth.approvers) that must each sign off, instead of any required_approvals approvers. Ignored unless requires_approval is true; when set, overrides required_approvals with len(required_approvers).
available_whenstring | nullNoneState condition (same restricted grammar as routers[].condition) gating whether this tool is even offered to the agent this turn — see LocalToolConfig.available_when for the full explanation. None (default) means always available, today's behavior.
untrusted_outputbooleanTrueMark this tool's return value as untrusted — see LocalToolConfig.untrusted_output for the full explanation. True by default for OpenAPI-derived tools, since they call an external API outside the project's own trust boundary; set false only for an API you fully control and trust.

RAGConfig

FieldTypeDefaultDescription
docs_dirstring'docs'Directory of documents to index for retrieval, relative to the project root.
embedding_modelstring'text-embedding-3-small'Embedding model used to vectorize documents and queries.
top_kinteger4Number of chunks retrieved per query.
chunk_sizeinteger500Maximum characters per indexed chunk.
chunk_overlapinteger50Characters of overlap between consecutive chunks.
hydebooleanFalseEnable Hypothetical Document Embeddings for advanced retrieval

RateLimitConfig

FieldTypeDefaultDescription
max_requests_per_windowinteger | nullNoneMax /chat, /chat/stream, /resume, or /stream requests one authenticated caller (tenant) may make within window_seconds. None (default) means unlimited. Enforced by counting that caller's rows in the run_logs audit table, so it only applies when memory.type is 'sqlite' or 'postgres' — the same scope run_logs itself has.
window_secondsinteger60Rolling window, in seconds, that max_requests_per_window is measured over.
max_cost_per_caller_per_daynumber | nullNoneMax total USD cost one authenticated caller may accrue in a rolling 24h window, summed from run_logs.cost_delta. None (default) means unlimited.
max_tokens_per_caller_per_dayinteger | nullNoneMax total tokens one authenticated caller may consume in a rolling 24h window, summed from run_logs.tokens_delta. None (default) means unlimited.

RootRouterConfig

FieldTypeDefaultDescription
descriptionstring | nullNoneWhat this router decides
modulestringrequiredPython module containing a route(state) function
possible_targetslist[string][]Strict list of allowed target agents to maintain determinism and UI visualization

RouterConfig

FieldTypeDefaultDescription
conditionstring | nullNonePython evaluation string against state (e.g., "balance < 0")
custom_modulestring | nullNoneModule to execute deterministic routing logic
targetstringrequiredAgent to route to when this router fires.

SandboxToolConfig

FieldTypeDefaultDescription
namestringrequiredTool name exposed to the LLM for tool-calling.
typestringrequiredDiscriminator — must be the literal string 'sandbox'.
language"python" | "bash"'python'Interpreter used to run the submitted code.
timeout_secondsinteger10Wall-clock limit before the sandboxed process is killed. Also used as the POSIX CPU-time rlimit (see runtime/sandbox.py) — a no-op on platforms without the resource module (Windows).
max_memory_mbinteger | null256POSIX address-space rlimit (RLIMIT_AS) applied to the sandboxed process, in megabytes. None disables the memory limit entirely. A no-op on platforms without the resource module (Windows).
requires_approvalbooleanFalseRequire human-in-the-loop approval before this tool actually executes.
required_approvalsinteger1Number of distinct approvers (see server.auth.approvers) who must each approve via /resume before this tool executes — 1 (default) matches today's single-approval behavior. Ignored unless requires_approval is true.
required_approverslist[string] | nullNoneSpecific approver ids (keys of server.auth.approvers) that must each sign off, instead of any required_approvals approvers. Ignored unless requires_approval is true; when set, overrides required_approvals with len(required_approvers).
available_whenstring | nullNoneState condition (same restricted grammar as routers[].condition) gating whether this tool is even offered to the agent this turn — see LocalToolConfig.available_when for the full explanation. None (default) means always available, today's behavior.
untrusted_outputbooleanTrueMark this tool's return value as untrusted — see LocalToolConfig.untrusted_output for the full explanation. True by default: sandboxed code's stdout/stderr can be influenced by whatever the executed code does (including content it read from elsewhere), so it's treated the same as an external tool result by default.

ServerConfig

FieldTypeDefaultDescription
authAuthConfig(factory default)Authentication configuration for inta serve/inta monitor. Defaults to no authentication — set this before exposing either beyond localhost.
webhook_urlstring | nullNoneWebhook URL for async HITL notifications
webhook_secret_env_varstring | nullNoneEnv var containing secret to authenticate webhooks
rate_limitRateLimitConfig(factory default)Per-caller rate limiting/usage quotas for the API server. All thresholds default to unlimited — opt in per project.

StateReducerConfig

FieldTypeDefaultDescription
keystringrequiredShared state key this reducer applies to.
strategy"overwrite" | "append" | "deep_merge"'overwrite'How concurrent/repeated writes to key are combined: 'overwrite' (last write wins), 'append' (to a list), or 'deep_merge' (for dicts).

StateWriteAction

FieldTypeDefaultDescription
keystringrequiredState key to write.
valueanyrequiredValue to write — the same JSON-ish value write_state accepts.

ToolReferenceConfig

FieldTypeDefaultDescription
namestringrequiredName of a tool or MCP/OpenAPI provider declared at the ai.yaml root.
available_whenstring | nullNoneState condition (same restricted grammar as routers[].condition) gating whether this tool is even offered to this agent this turn — see LocalToolConfig.available_when for the full explanation. This is the field that actually matters in practice: a per-agent tools: entry is usually a name-reference to a root-level tool, and availability is inherently agent-specific (the same globally-declared tool might be gated for one agent and unrestricted for another). None (default) means always available, today's behavior.

VoteConfig

FieldTypeDefaultDescription
strategy"majority" | "llm_judge"'majority'How a 'vote' workflow task's branch answers become one result: 'majority' compares branch outputs directly with no extra LLM call; 'llm_judge' asks the model to pick or synthesize the best answer from all branch outputs.
min_agreementnumber0.5Minimum fraction (0.0-1.0) of branches that must agree for 'majority' to declare a winner. Below this, no answer is guessed — the task reports 'no consensus' plus all branch outputs instead.

WorkflowTask

FieldTypeDefaultDescription
namestringrequiredTask name, used for logging/tracing this step of the workflow.
type"sequential" | "parallel" | "vote"'sequential''sequential' runs sub-tasks/agent one after another; 'parallel' runs them concurrently and appends every branch's result; 'vote' runs them concurrently like 'parallel' but aggregates branch answers into one consensus result (see vote).
agentstring | nullNoneAgent that executes this task.
instructionstring | nullNoneInstruction given to agent for this task.
taskslist[WorkflowTask] | nullNoneNested sub-tasks, when this task is a grouping node rather than a leaf agent call.
voteVoteConfig | nullNoneAggregation settings for a 'vote' task (ignored otherwise); defaults to majority voting with 50% minimum agreement when omitted.

Released under the Apache 2.0 License.