Skip to main content

Agent

Struct Agent 

Source
pub struct Agent { /* private fields */ }
Expand description

Builder for a single agent invocation.

Create with Agent::new, chain configuration methods, then call run with an AgentProvider to execute.

§Examples

use ironflow_core::prelude::*;

let provider = ClaudeCodeProvider::new();

let result = Agent::new()
    .system_prompt("You are a Rust expert.")
    .prompt("Review this code for safety issues.")
    .model(Model::OPUS)
    .allowed_tools(&["Read", "Grep"])
    .max_turns(5)
    .max_budget_usd(0.50)
    .working_dir("/tmp/project")
    .permission_mode(PermissionMode::Auto)
    .run(&provider)
    .await?;

println!("Cost: ${:.4}", result.cost_usd().unwrap_or(0.0));

Implementations§

Source§

impl Agent

Source

pub fn new() -> Self

Create a new agent builder with default settings.

Defaults: Model::SONNET, no system prompt, no tool restrictions, no budget/turn limits, PermissionMode::Default.

Source

pub fn from_config(config: impl Into<AgentConfig>) -> Self

Create an agent builder from an existing AgentConfig.

Useful when the config comes from a serialized workflow definition rather than being built programmatically.

§Examples
use ironflow_core::prelude::*;
use ironflow_core::provider::AgentConfig;

let provider = ClaudeCodeProvider::new();
let config = AgentConfig::new("Summarize the README");
let result = Agent::from_config(config).run(&provider).await?;
Source

pub fn system_prompt(self, prompt: &str) -> Self

Set the system prompt that defines the agent’s persona or constraints.

Source

pub fn prompt(self, prompt: &str) -> Self

Set the user prompt - the main instruction sent to the agent.

Source

pub fn model(self, model: impl Into<String>) -> Self

Set the model to use for this invocation.

Accepts any string-like value. Use Model constants for well-known Claude models, or pass an arbitrary string for custom providers.

Defaults to Model::SONNET if not called.

Source

pub fn allowed_tools(self, tools: &[&str]) -> Self

Restrict which tools the agent may invoke.

Pass an empty slice (or do not call this method) to allow the provider default set of tools.

Source

pub fn max_turns(self, turns: u32) -> Self

Set the maximum number of agentic turns.

§Panics

Panics if turns is 0.

Source

pub fn max_budget_usd(self, budget: f64) -> Self

Set the maximum spend in USD for this invocation.

§Panics

Panics if budget is negative, NaN, or infinity.

Source

pub fn working_dir(self, dir: &str) -> Self

Set the working directory for the agent process.

Source

pub fn mcp_config(self, config: &str) -> Self

Set the path to an MCP (Model Context Protocol) server configuration file.

Source

pub fn permission_mode(self, mode: PermissionMode) -> Self

Set the permission mode controlling tool-use approval behavior.

See PermissionMode for details on each variant.

Source

pub fn output<T: JsonSchema>(self) -> Self

Request structured (typed) output from the agent.

The type T must implement JsonSchema. The generated schema is sent to the provider so the model returns JSON conforming to T, which can then be deserialized with AgentResult::json.

§Examples
use ironflow_core::prelude::*;

#[derive(Deserialize, JsonSchema)]
struct Review {
    score: u8,
    summary: String,
}

let provider = ClaudeCodeProvider::new();
let result = Agent::new()
    .prompt("Review the codebase")
    .output::<Review>()
    .run(&provider)
    .await?;

let review: Review = result.json().expect("schema-validated output");
println!("Score: {}/10 - {}", review.score, review.summary);
Source

pub fn output_schema_raw(self, schema: &str) -> Self

Set structured output from a pre-serialized JSON Schema string.

Use this when the schema comes from configuration or another source rather than a Rust type. For type-safe schema generation, prefer output.

Important: structured output requires max_turns >= 2. The Claude CLI uses the first turn for reasoning and a second turn to produce the schema-conforming JSON.

§Examples
use ironflow_core::prelude::*;

let schema = r#"{"type":"object","properties":{"labels":{"type":"array","items":{"type":"string"}}}}"#;
let agent = Agent::new()
    .prompt("Classify this email")
    .output_schema_raw(schema);
Source

pub fn retry(self, max_retries: u32) -> Self

Retry the agent invocation up to max_retries times on transient failures.

Uses default exponential backoff settings (200ms initial, 2x multiplier, 30s cap). For custom backoff parameters, use retry_policy.

Only transient errors are retried: process failures and timeouts. Deterministic errors (prompt too large, schema validation) are never retried.

§Panics

Panics if max_retries is 0.

§Examples
use ironflow_core::prelude::*;

let provider = ClaudeCodeProvider::new();
let result = Agent::new()
    .prompt("Summarize the codebase")
    .retry(2)
    .run(&provider)
    .await?;
Source

pub fn retry_policy(self, policy: RetryPolicy) -> Self

Set a custom RetryPolicy for this agent invocation.

Allows full control over backoff duration, multiplier, and max delay. See RetryPolicy for details.

§Examples
use std::time::Duration;
use ironflow_core::prelude::*;
use ironflow_core::retry::RetryPolicy;

let provider = ClaudeCodeProvider::new();
let result = Agent::new()
    .prompt("Analyze the code")
    .retry_policy(
        RetryPolicy::new(3)
            .backoff(Duration::from_secs(1))
            .max_backoff(Duration::from_secs(60))
    )
    .run(&provider)
    .await?;
Source

pub fn dry_run(self, enabled: bool) -> Self

Enable or disable dry-run mode for this specific operation.

When dry-run is active, the agent call is logged but not executed. A synthetic AgentResult is returned with a placeholder text, zero cost, and zero tokens.

If not set, falls back to the global dry-run setting (see set_dry_run).

Source

pub fn log_sink(self, sink: Arc<dyn LogSink>) -> Self

Attach a LogSink for real-time log streaming.

When set, invoke_with_logs is called instead of invoke, allowing providers that support streaming to pipe output lines in real time.

§Examples
use std::sync::Arc;
use ironflow_core::prelude::*;

let provider = ClaudeCodeProvider::new();
let sink: Arc<dyn LogSink> = Arc::new(MySink);

let result = Agent::new()
    .prompt("Analyze src/")
    .log_sink(sink)
    .run(&provider)
    .await?;
Source

pub fn trace_context(self, ctx: WorkflowTraceContext) -> Self

Attach a WorkflowTraceContext for distributed tracing.

When set, the trace context is stored in the AgentConfig and made available to providers for injecting traceparent headers into outgoing HTTP requests.

§Examples
use ironflow_core::prelude::*;
use ironflow_core::trace_context::WorkflowTraceContext;

let provider = ClaudeCodeProvider::new();
let ctx = WorkflowTraceContext::new_root();

let result = Agent::new()
    .prompt("Analyze the code")
    .trace_context(ctx)
    .run(&provider)
    .await?;
Source

pub fn verbose(self) -> Self

Enable verbose/debug mode to capture the full conversation trace.

When enabled, the provider captures every assistant message and tool call into AgentResult::debug_messages. Useful for understanding why the agent returned an unexpected result.

§Examples
use ironflow_core::prelude::*;

let provider = ClaudeCodeProvider::new();

let result = Agent::new()
    .prompt("Analyze src/")
    .verbose()
    .max_budget_usd(0.10)
    .run(&provider)
    .await?;

if let Some(messages) = result.debug_messages() {
    for msg in messages {
        println!("{msg}");
    }
}
Source

pub fn resume(self, session_id: &str) -> Self

Resume a previous agent conversation by session ID.

Pass the session ID from a previous AgentResult::session_id() to continue the multi-turn conversation.

§Examples
use ironflow_core::prelude::*;

let provider = ClaudeCodeProvider::new();

let first = Agent::new()
    .prompt("Analyze the src/ directory")
    .max_budget_usd(0.10)
    .run(&provider)
    .await?;

let session = first.session_id().expect("provider returned session ID");

let followup = Agent::new()
    .prompt("Now suggest improvements")
    .resume(session)
    .max_budget_usd(0.10)
    .run(&provider)
    .await?;
§Panics

Panics if session_id is empty or contains characters other than alphanumerics, hyphens, and underscores.

Source

pub fn resume_environment(self, environment_id: &str) -> Self

Resume a persistent environment created by a previous agent step.

Pass the ID from a previous AgentResult::environment_id(): the agent finds the files the previous step left in its working volume. Combine it with resume to also continue the conversation. Only the K8s ephemeral provider configured with an environment volume honours it; other providers ignore it.

§Examples
use ironflow_core::prelude::*;

// `provider` is a `K8sEphemeralProvider` with an `environment_volume`.
let first = Agent::new()
    .prompt("Clone the repository and install the dependencies")
    .max_budget_usd(0.10)
    .run(provider)
    .await?;

let environment = first.environment_id().expect("environment volume configured");

let followup = Agent::new()
    .prompt("Run the test suite")
    .resume_environment(environment)
    .max_budget_usd(0.10)
    .run(provider)
    .await?;
§Panics

Panics if environment_id is empty, longer than 253 characters, or contains characters other than lowercase ASCII letters, digits and hyphens.

Source

pub async fn run( self, provider: &dyn AgentProvider, ) -> Result<AgentResult, OperationError>

Execute the agent invocation using the given AgentProvider.

If a retry_policy is configured, transient failures (process crashes, timeouts, schema validation) are retried with exponential backoff. When structured output is requested (json_schema is set) and no explicit retry policy is configured, an automatic retry policy of 2 retries is applied to handle non-deterministic structured_output: null responses from the CLI. Deterministic errors (prompt too large) are returned immediately without retry.

§Errors

Returns OperationError::Agent if the provider reports a failure (process crash, timeout, or schema validation error).

§Panics

Panics if prompt was never called or the prompt is empty (whitespace-only counts as empty).

Trait Implementations§

Source§

impl Default for Agent

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for Agent

§

impl !UnwindSafe for Agent

§

impl Freeze for Agent

§

impl Send for Agent

§

impl Sync for Agent

§

impl Unpin for Agent

§

impl UnsafeUnpin for Agent

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more