Skip to content

Agent

Concepts: Agent.

Agent

Agent(model: str | Model, *, system: str | None = None, tools: Iterable[Any] = (), skills: Iterable[str] = (), loop: Any = None, reporter: Reporter | None = DEFAULT, human: Human | None = DEFAULT, name: str | None = None, description: str | None = None)

An agent's settings, and the actions that need a model, tools or a human.

Settings do not change after creation. Use copy to get an Agent with different settings. The history of a run lives in a State, and the order of steps is decided by the loop.

Example
agent = Agent(model="claude-sonnet-5", system="You are a coding assistant", tools=[read_file])
answer = agent.run("Find the bug in main.py")

Creates an Agent. Mistakes in the settings are reported here, with how to fix them.

Creating an Agent uses no network and needs no API key.

Parameters:

Name Type Description Default
model str | Model

A model name such as "claude-sonnet-5", "anthropic/claude-sonnet-5" or "ollama/llama3:8b", or a Model object such as Anthropic(...) when you need settings.

required
system str | None

The system prompt.

None
tools Iterable[Any]

@tool functions, objects with @tool methods, single @tool methods, MCP servers and single MCP tools (github.create_issue).

()
skills Iterable[str]

Not implemented yet. A non-empty value raises NotImplementedError.

()
loop Any

The loop run calls with (agent, state). Defaults to default_loop.

None
reporter Reporter | None

Receives progress notifications. Defaults to the shared Terminal. None is silent.

DEFAULT
human Human | None

Answers ask_human. Defaults to the shared Terminal. None means no human.

DEFAULT
name str | None

The Agent's name.

None
description str | None

What the Agent does.

None

Raises:

Type Description
TypeError

A setting has the wrong type, for example a function without @tool in tools=, a loop that is not callable, or a Reporter or Human class instead of an object.

ValueError

Two tools share a name, or the model string is ambiguous.

model property

model: Model

The Model object. A model string given to Agent(model=...) is already turned into one.

system property

system: str | None

The system prompt, or None.

tools property

tools: tuple[Any, ...]

The items passed in tools=, as given.

loop property

loop: Any

The loop run calls. default_loop unless loop= was given.

reporter property

reporter: Reporter | None

The Reporter that receives progress notifications, or None. Defaults to the shared Terminal.

human property

human: Human | None

The Human that answers ask_human, or None. Defaults to the shared Terminal.

name property

name: str | None

The Agent's name, or None.

description property

description: str | None

What the Agent does, or None.

run

run(task: str | State) -> Any

Runs the loop on a task and returns what the loop returns, usually the answer.

MCP servers in tools= connect for the run and disconnect after it, unless with agent: keeps them open. If an exception leaves the run, it is recorded in state.history, tool calls still waiting for a result are closed ((interrupted by user) after Ctrl+C), and the exception is raised as is. After Ctrl+C you can call run again with the same State.

Parameters:

Name Type Description Default
task str | State

A task string, which starts a new State, or a State to continue.

required

Returns:

Type Description
Any

What the loop returns. The default loop returns state.answer.

Raises:

Type Description
TypeError

The loop is async (use arun), or task is neither a string nor a State.

ValueError

The State was already ended with state.finish().

Example
state = State("Find the bug in this repo")
answer = agent.run(state)
print(state.stopped_by, state.usage.cost)

arun async

arun(task: str | State) -> Any

The async version of run.

Uses this Agent's loop if it is async, or adefault_loop if the Agent uses the default loop. Cancelling the task follows the same rules as Ctrl+C in run.

Parameters:

Name Type Description Default
task str | State

A task string, which starts a new State, or a State to continue.

required

Returns:

Type Description
Any

What the loop returns. The default loop returns state.answer.

Raises:

Type Description
TypeError

The loop is a sync loop other than default_loop, which would block the event loop.

ValueError

The State was already ended with state.finish().

think

think(state: State, tools: Iterable[Any] | None = None) -> None

Sends the context to the model once and records its reply in the State.

The reply may ask for tool calls. Check state.wants_tools() and run them with use_tools. If anything fails, the context goes back to how it was before this call, and the error is raised.

Parameters:

Name Type Description Default
state State

The State to continue. The first Agent that thinks on a State owns it.

required
tools Iterable[Any] | None

Which of this Agent's tools the model may see this turn. None shows all of them, [] shows none.

None

Raises:

Type Description
ValueError

The State is finished, still has tool calls waiting for results, belongs to another Agent, or tools has a tool this Agent does not have.

ProviderError

The model provider failed (RateLimitError, AuthError, ContextTooLongError or another ProviderError).

athink async

athink(state: State, tools: Iterable[Any] | None = None) -> None

The async version of think. Cancelling it rolls the context back like any other failure.

use_tools

use_tools(state: State) -> None

Runs the tool calls from the last reply and records their results in the State.

Calls to tools made with parallel=True (the default) run at the same time, then the rest run one by one. Does nothing if there are no calls. A tool that raises does not become an error result: results of the calls that finished are recorded, and the exception is raised as is. Invalid arguments and unknown tool names go back to the model as (input error: ...) results.

Parameters:

Name Type Description Default
state State

The State whose pending_calls to run.

required

Raises:

Type Description
ValueError

The State is finished or belongs to another Agent.

ause_tools async

ause_tools(state: State) -> None

The async version of use_tools.

async def tools run as tasks on the running event loop, other tools on worker threads. Cancelling it follows the same rules as Ctrl+C.

ask

ask(state: State, prompt: str, returns: Any = str, *, retries: int = 2) -> Any

Asks the model a question about the current context and returns the answer in the returns format.

The question and answer are recorded in state.history but do not enter the context, so the run continues as if the question was never asked. The model cannot call tools while answering. Any Agent can ask about a State, not only the one running it.

Parameters:

Name Type Description Default
state State

The State whose context the model reads.

required
prompt str

The question.

required
returns Any

The answer format: str, a dataclass or a Pydantic model.

str
retries int

How many more times to ask when the answer does not fit returns.

2

Returns:

Type Description
Any

The answer, converted to returns.

Raises:

Type Description
TypeError

returns is not a supported format.

ValueError

The State is finished.

OutputError

The answer still did not fit returns after retries more tries.

ProviderError

The model provider failed.

Example
@dataclass
class Review:
    approved: bool
    reason: str

review = agent.ask(state, "Is this change safe to merge?", returns=Review)

aask async

aask(state: State, prompt: str, returns: Any = str, *, retries: int = 2) -> Any

The async version of ask.

ask_human

ask_human(state: State, prompt: str, returns: Any = str) -> Any

Asks the person through human and returns the answer in the returns format.

The question and answer are recorded in state.history. The context does not change.

Parameters:

Name Type Description Default
state State

The State of the current run.

required
prompt str

The question.

required
returns Any

The answer format: str, bool or Literal[...] for a fixed set of choices.

str

Returns:

Type Description
Any

The answer, converted to returns.

Raises:

Type Description
NoHumanError

The Agent was created with human=None.

TypeError

returns is not a supported format, or the Human only answers asynchronously (use aask_human).

Example
choice = agent.ask_human(state, "Run the command?", returns=Literal["yes", "no", "always"])

aask_human async

aask_human(state: State, prompt: str, returns: Any = str) -> Any

The async version of ask_human.

Awaits human.aask when the Human has it, and otherwise runs human.ask on a worker thread.

compact

compact(state: State, instructions: str | None = None) -> None

Asks the model to summarize the context, then replaces the context with the task and that summary.

state.history keeps everything. If anything fails, the context is left unchanged. In a loop, compact_if_full calls this only when the context is getting full.

Parameters:

Name Type Description Default
state State

The State to compact.

required
instructions str | None

What the summary should keep, for example "Keep file paths and failing tests".

None

Raises:

Type Description
ValueError

The State still has tool calls waiting for results, or belongs to another Agent.

OutputError

The model returned an empty summary.

ProviderError

The model provider failed.

acompact async

acompact(state: State, instructions: str | None = None) -> None

The async version of compact.

copy

copy(**changes: Any) -> Agent

Returns a new Agent with some settings changed. The original Agent does not change.

The new Agent goes through the same checks as Agent(...).

Parameters:

Name Type Description Default
**changes Any

Settings to change, by the same names as the Agent(...) arguments.

{}

Returns:

Type Description
Agent

The new Agent.

Raises:

Type Description
TypeError

A name in changes is not a setting.

Example
quiet = agent.copy(model=FakeModel(["Done"]), reporter=None)