toolAgent

fun toolAgent(model: ChatModel, tools: List<Tool> = emptyList(), system: String? = null, inOrder: Boolean = false, tokenBudget: Int? = null, retry: Retry? = null): CompiledGraph<AgentState>

Returns a graph that is a tool-calling agent: model answers the conversation in the state, and runs tools as often as it needs to before it answers.

val agent = toolAgent(model, tools = listOf(forecast), system = "You are a travel assistant.")

val first = agent.invoke(AgentState("What is the weather in Madrid?")).state
println(first.answer)
val second = agent.invoke(first.withUserMessage("And in Lisbon?")).state

// Or show the answer while the model writes it.
agent.stream(AgentState("What is the weather in Madrid?")).collect { event -> event.textDelta?.let(::print) }

The graph is a toolLoop with its default node names. Use toolLoop directly to put the agent inside a larger graph, or to keep the conversation in a state of your own.

The state counts the tokens of the conversation in AgentState.tokens. With a tokenBudget, the model is not asked again once the count has reached it, and the run ends without an answer:

val agent = toolAgent(model, tools = listOf(forecast), tokenBudget = 50_000)

val state = agent.invoke(AgentState("Plan a week in Portugal.")).state
println("${state.tokens.total} tokens")
if (state.answer == null) println("The agent used its budget before it had an answer.")

Parameters

inOrder

true to run the tool calls of an answer one after the other, in the order the model wrote them, for tools that depend on each other. By default they run at the same time.

tokenBudget

the tokens the conversation in the state may use. The count is compared with it before each call to the model, with the numbers of the calls so far, so a run ends up to one call above it. null is no limit.

retry

how the model is asked again when a call to it fails, for example Retry(attempts = 3). null ends the run at the first failure.

Throws

if two tools have the same name, or tokenBudget is less than 1.