#[non_exhaustive]pub struct AgentConfig<Tools = NoTools, Schema = NoSchema> {Show 20 fields
pub system_prompt: Option<String>,
pub prompt: String,
pub model: String,
pub allowed_tools: Vec<String>,
pub disallowed_tools: Vec<String>,
pub max_turns: Option<u32>,
pub max_budget_usd: Option<f64>,
pub working_dir: Option<String>,
pub mcp_config: Option<String>,
pub strict_mcp_config: bool,
pub bare: bool,
pub permission_mode: PermissionMode,
pub json_schema: Option<String>,
pub resume_session_id: Option<String>,
pub verbose: bool,
pub pod_labels: BTreeMap<String, String>,
pub inputs: Vec<AgentInput>,
pub allow_failure: bool,
pub retry: Option<RetryPolicy>,
pub trace_context: Option<WorkflowTraceContext>,
/* private fields */
}Expand description
Serializable configuration passed to an AgentProvider for a single invocation.
Built by Agent::run from the builder state.
Provider implementations translate these fields into whatever format the underlying
backend expects.
§Typestate: tools vs structured output
Claude CLI has a known bug
where combining --json-schema with --allowedTools always returns
structured_output: null. To prevent this at compile time, allow_tool
and output / output_schema_raw are mutually
exclusive: using one removes the other from the available API.
use ironflow_core::provider::AgentConfig;
// OK: tools only
let _ = AgentConfig::new("search").allow_tool("WebSearch");
// OK: structured output only
let _ = AgentConfig::new("classify").output_schema_raw(r#"{"type":"object"}"#);use ironflow_core::provider::AgentConfig;
// COMPILE ERROR: cannot add tools after setting structured output
let _ = AgentConfig::new("x").output_schema_raw("{}").allow_tool("Read");use ironflow_core::provider::AgentConfig;
// COMPILE ERROR: cannot set structured output after adding tools
let _ = AgentConfig::new("x").allow_tool("Read").output_schema_raw("{}");Workaround: split the work into two steps – one agent with tools to
gather data, then a second agent with .output::<T>() to structure the result.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.system_prompt: Option<String>Optional system prompt that sets the agent’s persona or constraints.
prompt: StringThe user prompt - the main instruction to the agent.
model: StringWhich model to use for this invocation.
Accepts any string. Use Model constants for well-known Claude models
(e.g. Model::SONNET), or pass a custom identifier for other providers.
allowed_tools: Vec<String>Allowlist of tool names the agent may invoke (empty = provider default).
disallowed_tools: Vec<String>Denylist of tool names the agent MUST NOT invoke.
Maps to --disallowedTools on the Claude CLI. Unlike
allowed_tools, this does not activate any
tools; it only filters out tools that would otherwise be loaded by
default. As such, it is safe to combine with structured output
(output) without triggering the Claude CLI bug that
affects --json-schema + --allowedTools.
max_turns: Option<u32>Maximum number of agentic turns before the provider should stop.
max_budget_usd: Option<f64>Maximum spend in USD for this single invocation.
working_dir: Option<String>Working directory for the agent process.
mcp_config: Option<String>Path to an MCP server configuration file.
strict_mcp_config: boolWhen true, pass --strict-mcp-config to the Claude CLI so it only
loads MCP servers from mcp_config and ignores
any global/user MCP configuration (e.g. ~/.claude.json).
Useful to prevent global MCP servers from leaking tools into steps
that request structured_output, which triggers the Claude CLI bug
where --json-schema combined with any active tool returns
structured_output: null. See
https://github.com/anthropics/claude-code/issues/18536.
Combine with mcp_config set to a file containing
{"mcpServers":{}} to disable every MCP server for the invocation.
bare: boolWhen true, pass --bare to Claude CLI. Bare mode disables:
- auto-memory (automatic creation of
~/.claude/.../memory/*.mdfiles) CLAUDE.mdauto-discovery (no global/projectCLAUDE.mdloaded)- hooks, LSP, plugin sync, attribution, background prefetches
Recommended for orchestrator agents that should not have any implicit side effects on the user’s filesystem or inherit user-level context.
§Authentication requirement
--bare is only compatible with an Anthropic API key
(ANTHROPIC_API_KEY environment variable). It does not work with
OAuth authentication (claude /login / keychain-stored credentials),
because bare mode disables keychain reads.
permission_mode: PermissionModePermission mode controlling how the agent handles tool-use approvals.
json_schema: Option<String>Optional JSON Schema string. When set, the provider should request structured (typed) output from the model.
resume_session_id: Option<String>Optional session ID to resume a previous conversation.
When set, the provider should continue the conversation from the specified session rather than starting a new one.
verbose: boolEnable verbose/debug mode to capture the full conversation trace.
When true, the provider uses streaming output (stream-json) to
record every assistant message and tool call. The resulting
AgentOutput::debug_messages field will contain the conversation
trace for inspection.
pod_labels: BTreeMap<String, String>Custom labels applied to the pod (K8s providers only).
Non-K8s providers ignore this field. Labels are merged with the provider-level pod labels and the hardcoded ironflow labels. In case of conflict, hardcoded labels always win, then invocation-level labels, then provider-level defaults.
inputs: Vec<AgentInput>External inputs to materialize on the agent’s filesystem before invocation.
See AgentInput for the semantics. The provider is responsible for
fetching each URL and placing it at mount_path before the agent runs.
Add inputs with AgentConfig::input_file.
allow_failure: boolWhen true, a failure of this step does not fail the run.
retry: Option<RetryPolicy>Optional step-level retry policy.
trace_context: Option<WorkflowTraceContext>Optional W3C trace context for distributed tracing propagation.
When set, providers can inject the traceparent header into
outgoing HTTP requests (LLM APIs, MCP servers) to correlate
workflow spans with downstream service spans.
Implementations§
Source§impl AgentConfig
impl AgentConfig
Source§impl<Tools, Schema> AgentConfig<Tools, Schema>
impl<Tools, Schema> AgentConfig<Tools, Schema>
Sourcepub fn system_prompt(self, prompt: &str) -> Self
pub fn system_prompt(self, prompt: &str) -> Self
Set the system prompt.
Sourcepub fn max_budget_usd(self, budget: f64) -> Self
pub fn max_budget_usd(self, budget: f64) -> Self
Set the maximum budget in USD.
Sourcepub fn working_dir(self, dir: &str) -> Self
pub fn working_dir(self, dir: &str) -> Self
Set the working directory.
Sourcepub fn permission_mode(self, mode: PermissionMode) -> Self
pub fn permission_mode(self, mode: PermissionMode) -> Self
Set the permission mode.
Sourcepub fn mcp_config(self, config: &str) -> Self
pub fn mcp_config(self, config: &str) -> Self
Set the MCP server configuration file path.
Sourcepub fn strict_mcp_config(self, strict: bool) -> Self
pub fn strict_mcp_config(self, strict: bool) -> Self
Enable strict MCP config mode.
When true, the Claude CLI is invoked with --strict-mcp-config,
which disables loading of any MCP server defined outside the
mcp_config file (the global ~/.claude.json
and user-level configs are ignored).
This is the recommended way to prevent global MCP servers from
silently injecting tools into a structured-output step and
triggering the Claude CLI bug that returns structured_output: null
whenever any tool is active. See
https://github.com/anthropics/claude-code/issues/18536.
§Examples
use ironflow_core::provider::AgentConfig;
use schemars::JsonSchema;
#[derive(serde::Deserialize, JsonSchema)]
struct Out { ok: bool }
// Isolate the step from any global MCP server so structured output works.
let config = AgentConfig::new("classify this")
.strict_mcp_config(true)
.mcp_config(r#"{"mcpServers":{}}"#)
.output::<Out>();Sourcepub fn bare(self, enabled: bool) -> Self
pub fn bare(self, enabled: bool) -> Self
Enable bare mode (minimal Claude Code environment, see --bare).
When true, the Claude CLI is invoked with --bare, which disables:
- auto-memory (no automatic
~/.claude/.../memory/*.mdfile creation) CLAUDE.mdauto-discovery (neither global nor project-level)- hooks, LSP, plugin sync, attribution, background prefetches, keychain reads
Sets CLAUDE_CODE_SIMPLE=1 in the child process.
Recommended for orchestrator steps that should not have any implicit side effects on the user’s filesystem or inherit user-level context (email, preferences, etc.).
§Authentication requirement
--bare is only compatible with an Anthropic API key
(ANTHROPIC_API_KEY environment variable). It does not work with
OAuth authentication (claude /login / keychain-stored credentials),
because bare mode disables keychain reads. Invoking a bare agent on an
OAuth-only host will fail with an authentication error.
§Examples
use ironflow_core::provider::AgentConfig;
let config = AgentConfig::new("classify this")
.bare(true);Sourcepub fn allow_failure(self) -> Self
pub fn allow_failure(self) -> Self
Mark this step as allowed to fail without stopping the run.
§Examples
use ironflow_core::provider::AgentConfig;
let config = AgentConfig::new("lint the code").allow_failure();
assert!(config.allow_failure);Sourcepub fn disallowed_tools<I, S>(self, tools: I) -> Self
pub fn disallowed_tools<I, S>(self, tools: I) -> Self
Replace the entire disallowed-tools list.
Maps to --disallowedTools on the Claude CLI. This method is available
on every typestate variant (including
AgentConfig<NoTools, WithSchema>) because, unlike
allow_tool, disallowed_tools does not
activate any tool – it only filters out tools that would otherwise be
loaded by default.
As such, it is safe to combine with structured output:
§Examples
use ironflow_core::provider::AgentConfig;
use schemars::JsonSchema;
#[derive(serde::Deserialize, JsonSchema)]
struct Out { ok: bool }
let config = AgentConfig::new("classify this")
.disallowed_tools(["Write", "Edit"])
.output::<Out>();Sourcepub fn pod_label(self, key: &str, value: &str) -> Self
pub fn pod_label(self, key: &str, value: &str) -> Self
Add a single custom pod label (K8s providers only).
Can be called multiple times. Non-K8s providers ignore this field.
§Examples
use ironflow_core::provider::AgentConfig;
let config = AgentConfig::new("analyze")
.pod_label("ironflow.io/network-profile", "grafana-only")
.pod_label("team", "observability");Sourcepub fn pod_labels(self, labels: BTreeMap<String, String>) -> Self
pub fn pod_labels(self, labels: BTreeMap<String, String>) -> Self
Replace the entire custom pod labels map (K8s providers only).
Non-K8s providers ignore this field.
§Examples
use std::collections::BTreeMap;
use ironflow_core::provider::AgentConfig;
let mut labels = BTreeMap::new();
labels.insert("env".to_string(), "staging".to_string());
let config = AgentConfig::new("deploy").pod_labels(labels);Sourcepub fn resume(self, session_id: &str) -> Self
pub fn resume(self, session_id: &str) -> Self
Set a session ID to resume a previous conversation.
Sourcepub fn retry_policy(self, policy: RetryPolicy) -> Self
pub fn retry_policy(self, policy: RetryPolicy) -> Self
Set a step-level retry policy.
§Examples
use ironflow_core::provider::AgentConfig;
use ironflow_core::retry::RetryPolicy;
let config = AgentConfig::new("Summarize this document")
.retry_policy(RetryPolicy::new(3));
assert!(config.retry.is_some());Sourcepub fn trace_context(self, ctx: WorkflowTraceContext) -> Self
pub fn trace_context(self, ctx: WorkflowTraceContext) -> Self
Attach a WorkflowTraceContext for distributed tracing.
When set, providers can inject the traceparent header into
outgoing HTTP requests to correlate workflow spans with
downstream service spans.
§Examples
use ironflow_core::provider::AgentConfig;
use ironflow_core::trace_context::WorkflowTraceContext;
let ctx = WorkflowTraceContext::new_root();
let config = AgentConfig::new("classify this")
.trace_context(ctx);
assert!(config.trace_context.is_some());Sourcepub fn input_file(self, url: &str, mount_path: &str) -> Self
pub fn input_file(self, url: &str, mount_path: &str) -> Self
Declare an external input that the provider must materialize on the agent’s filesystem before invocation.
url is fetched (HTTP/HTTPS) and written to mount_path (absolute
path) inside the agent’s runtime. Each provider materializes inputs
in its own way:
- Local provider: downloads to a temp dir on the host.
- K8s providers: spawn a
curlimages/curlinitContainer that downloads into a sharedemptyDirmounted on the main container.
Can be called multiple times to declare several inputs.
§Examples
use ironflow_core::provider::AgentConfig;
let config = AgentConfig::new("Read /work/dossier.pdf and summarize")
.allow_tool("Read")
.input_file("https://r2.example.com/dossier.pdf", "/work/dossier.pdf");Source§impl<Tools> AgentConfig<Tools, NoSchema>
impl<Tools> AgentConfig<Tools, NoSchema>
Sourcepub fn allow_tool(self, tool: &str) -> AgentConfig<WithTools, NoSchema>
pub fn allow_tool(self, tool: &str) -> AgentConfig<WithTools, NoSchema>
Add an allowed tool.
Can be called multiple times to allow several tools. Returns an
AgentConfig<WithTools, NoSchema>, which cannot call
output or output_schema_raw.
This restriction exists because Claude CLI has a
known bug
where --json-schema combined with --allowedTools always returns
structured_output: null.
Workaround: use two sequential agent steps – one with tools to
gather data, then one with .output::<T>() to structure the result.
§Examples
use ironflow_core::provider::AgentConfig;
let config = AgentConfig::new("search the web")
.allow_tool("WebSearch")
.allow_tool("WebFetch");use ironflow_core::provider::AgentConfig;
// ERROR: cannot set structured output after adding tools
let _ = AgentConfig::new("x")
.allow_tool("Read")
.output_schema_raw(r#"{"type":"object"}"#);Source§impl<Schema> AgentConfig<NoTools, Schema>
impl<Schema> AgentConfig<NoTools, Schema>
Sourcepub fn output<T: JsonSchema>(self) -> AgentConfig<NoTools, WithSchema>
pub fn output<T: JsonSchema>(self) -> AgentConfig<NoTools, WithSchema>
Set structured output from a Rust type implementing JsonSchema.
The schema is serialized once at build time. When set, the provider will request typed output conforming to this schema.
Important: structured output requires max_turns >= 2.
Returns an AgentConfig<NoTools, WithSchema>, which cannot
call allow_tool.
This restriction exists because Claude CLI has a
known bug
where --json-schema combined with --allowedTools always returns
structured_output: null.
Workaround: use two sequential agent steps – one with tools to
gather data, then one with .output::<T>() to structure the result.
§Known limitations of Claude CLI structured output
The Claude CLI does not guarantee strict schema conformance for structured output. The following upstream bugs affect the behavior:
- Schema flattening (anthropics/claude-agent-sdk-python#502):
a schema like
{"type":"object","properties":{"items":{"type":"array",...}}}may return a bare array instead of the wrapper object. The CLI non-deterministically flattens schemas with a single array field. - Non-deterministic wrapping (anthropics/claude-agent-sdk-python#374): the same prompt can produce differently wrapped output across runs.
- No conformance guarantee (anthropics/claude-code#9058): the CLI does not validate output against the provided JSON schema.
Because of these bugs, ironflow’s provider layer applies multiple
fallback strategies when extracting the structured value (see
extract_structured_value).
§Examples
use ironflow_core::provider::AgentConfig;
use schemars::JsonSchema;
#[derive(serde::Deserialize, JsonSchema)]
struct Labels { labels: Vec<String> }
let config = AgentConfig::new("classify this text")
.output::<Labels>();use ironflow_core::provider::AgentConfig;
use schemars::JsonSchema;
#[derive(serde::Deserialize, JsonSchema)]
struct Out { x: i32 }
// ERROR: cannot add tools after setting structured output
let _ = AgentConfig::new("x").output::<Out>().allow_tool("Read");§Panics
Panics if the schema generated by schemars cannot be serialized
to JSON. This indicates a bug in the type’s JsonSchema derive,
not a recoverable runtime error.
Sourcepub fn output_schema_raw(self, schema: &str) -> AgentConfig<NoTools, WithSchema>
pub fn output_schema_raw(self, schema: &str) -> AgentConfig<NoTools, WithSchema>
Set structured output from a pre-serialized JSON Schema string.
Returns an AgentConfig<NoTools, WithSchema>, which cannot
call allow_tool. See output
for the rationale and workaround.
Trait Implementations§
Source§impl<Tools: Clone, Schema: Clone> Clone for AgentConfig<Tools, Schema>
impl<Tools: Clone, Schema: Clone> Clone for AgentConfig<Tools, Schema>
Source§fn clone(&self) -> AgentConfig<Tools, Schema>
fn clone(&self) -> AgentConfig<Tools, Schema>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more