Skip to main content

AgentRole

Trait AgentRole 

Source
pub trait AgentRole {
    type Input;
    type Output: DeserializeOwned + JsonSchema + AgentAnswer;

Show 14 methods // Required method fn prompt(&self, input: Self::Input) -> String; // Provided methods fn name(&self) -> &str { ... } fn system_prompt(&self) -> Option<&str> { ... } fn append_system_prompt(&self) -> Option<&str> { ... } fn tools(&self) -> Vec<Tool> { ... } fn permission_mode(&self) -> Option<PermissionMode> { ... } fn mcp_config(&self) -> Option<&str> { ... } fn strict_mcp_config(&self) -> bool { ... } fn model(&self) -> Option<&str> { ... } fn max_budget_usd(&self) -> Option<f64> { ... } fn max_turns(&self) -> Option<u32> { ... } fn effort(&self) -> Option<Effort> { ... } fn timeout(&self) -> Option<Duration> { ... } fn task(&self, input: Self::Input) -> AgentTask<Self::Output> { ... }
}
Expand description

A reusable agent with a fixed role: persona, tools, rights and output type.

Only prompt is required. The persona, tools, permission mode, MCP config and output type are locked by the role: the caller of task cannot change them (a role with more rights is another role). The model, budget, turn limit, effort, timeout and per-call settings are defaults the caller may override on the AgentTask.

§Examples

use ironflow_engine::config::{AgentAnswer, AgentRole, AgentStep, Tool};
use schemars::JsonSchema;
use serde::Deserialize;

#[derive(Deserialize, JsonSchema, AgentAnswer)]
struct Verdict {
    approved: bool,
}

struct Reviewer;

impl AgentRole for Reviewer {
    type Input = String;
    type Output = Verdict;

    fn prompt(&self, input: String) -> String {
        format!("Review: {input}")
    }

    fn append_system_prompt(&self) -> Option<&str> {
        Some("You are a strict reviewer.")
    }

    fn tools(&self) -> Vec<Tool> {
        vec![Tool::Read]
    }

    fn max_turns(&self) -> Option<u32> {
        Some(4)
    }
}

let config = Reviewer.task("diff".to_string()).max_budget_usd(0.10).into_config();
assert_eq!(config.append_system_prompt.as_deref(), Some("You are a strict reviewer."));
assert_eq!(config.allowed_tools, vec!["Read"]);
assert!(config.json_schema.is_some());
assert_eq!(config.max_budget_usd, Some(0.10));

Calling it from a workflow:

let verdict: Verdict = ctx.agent("review", Reviewer.task(diff)).await?;

Required Associated Types§

Source

type Input

What the caller passes to task to build the prompt.

Source

type Output: DeserializeOwned + JsonSchema + AgentAnswer

What the role answers; ctx.agent returns it. Its free-text fields are AgentText: see AgentAnswer.

Required Methods§

Source

fn prompt(&self, input: Self::Input) -> String

The prompt of one task. Required.

Provided Methods§

Source

fn name(&self) -> &str

Name of the role, recorded on every step it runs and shown by the API, CLI and dashboard. Defaults to the type name without its module path (Reviewer). Override it to keep the name stable across a type rename.

Renaming the type changes the default name: the steps and costs of the role are then split between the old and the new name. The caller of task cannot override it.

§Examples
struct Reviewer;

impl AgentRole for Reviewer {
    type Input = String;
    type Output = Verdict;

    fn prompt(&self, input: String) -> String {
        input
    }
}

struct Named;

impl AgentRole for Named {
    type Input = String;
    type Output = Verdict;

    fn name(&self) -> &str {
        "code-reviewer"
    }

    fn prompt(&self, input: String) -> String {
        input
    }
}

assert_eq!(Reviewer.name(), "Reviewer");
assert_eq!(Named.name(), "code-reviewer");
let config = Named.task("diff".to_string()).into_config();
assert_eq!(config.role.as_deref(), Some("code-reviewer"));
Source

fn system_prompt(&self) -> Option<&str>

Replaces the provider system prompt. Claude Code loses its own (tools, skills) when it is replaced. None by default.

Source

fn append_system_prompt(&self) -> Option<&str>

Persona appended to the provider system prompt. Prefer it to system_prompt for a role with tools. None by default.

Source

fn tools(&self) -> Vec<Tool>

Tools the role may use. None by default.

Source

fn permission_mode(&self) -> Option<PermissionMode>

Permission mode of the role; None keeps the AgentConfig::new default.

Source

fn mcp_config(&self) -> Option<&str>

MCP configuration, as JSON or a path. None by default.

Source

fn strict_mcp_config(&self) -> bool

Restrict the MCP servers to mcp_config. false by default.

Source

fn model(&self) -> Option<&str>

Default model; None keeps the AgentConfig::new default. The caller may override it.

Source

fn max_budget_usd(&self) -> Option<f64>

Default budget in USD. The caller may override it.

Source

fn max_turns(&self) -> Option<u32>

Default turn limit. The caller may override it.

A structured output needs at least 2 turns; like AgentStepConfig, the role does not validate it.

Source

fn effort(&self) -> Option<Effort>

Default effort. The caller may override it.

Source

fn timeout(&self) -> Option<Duration>

Default step timeout, see AgentConfig::timeout. The caller may override it.

Source

fn task(&self, input: Self::Input) -> AgentTask<Self::Output>

Build one task of this role.

§Panics

Panics if name is empty or blank, has leading or trailing whitespace, or is longer than MAX_ROLE_NAME_LEN bytes.

§Examples
let config = Reviewer.task("diff".to_string()).into_config();
assert_eq!(config.prompt, "Review: diff");

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§