Package-level declarations

Types

Link copied to clipboard
@Serializable
data class AgentState(val messages: List<ChatMessage> = emptyList(), val tokens: TokenUsage = TokenUsage())

The state of a toolAgent: the conversation so far, oldest message first, and what it cost.

Link copied to clipboard
sealed interface Answer

What a DecisionModel answered to one Question.

Link copied to clipboard

A DecisionModel that asks a ChatModel, so that choose, isYes, score and decisionEdge work with the model an app already has: Claude, OpenAI, Gemini, Ollama, or any other.

Link copied to clipboard
sealed interface ChatEvent

What a ChatModel emits while it writes an answer. See ChatModel.stream.

Link copied to clipboard
@Serializable
sealed interface ChatMessage

One message of a conversation with a ChatModel.

Link copied to clipboard
fun interface ChatModel

A language model that continues a conversation. It is the only thing the rest of this module needs from a model provider, so a graph written against it runs on every Kotlin target and with any provider.

Link copied to clipboard
class ChatModelException(message: String, cause: Throwable? = null) : TelarException

A call to a ChatModel failed: the provider could not be reached, it returned an error, or the model declined to answer.

Link copied to clipboard
data class ChatRequest(val messages: List<ChatMessage>, val system: String? = null, val tools: List<ToolSpec> = emptyList())

What a ChatModel is asked.

Link copied to clipboard
data class ChatResponse(val message: ChatMessage.Assistant, val usage: TokenUsage? = null)

What a ChatModel answered.

Link copied to clipboard
fun interface DecisionModel

A model that decides instead of writing: it picks one of the options you give it, answers yes or no, or rates something on a scale, and says how sure it is. Such a model is fast and cheap, and its answer has a fixed type, which makes it a good fit for the places where a graph has to decide: which node comes next, whether an answer is good enough, whether a person has to look.

Link copied to clipboard
class DecisionModelException(message: String, cause: Throwable? = null) : TelarException

A call to a DecisionModel failed: the provider could not be reached, it returned an error, or its answer does not fit the question.

Link copied to clipboard
data class DecisionRequest(val state: JsonElement, val questions: Map<String, Question>)

What a DecisionModel is asked.

Link copied to clipboard
data class DecisionResponse(val answers: Map<String, Answer>, val usage: TokenUsage? = null)

What a DecisionModel answered.

Link copied to clipboard
@SerialInfo
@Target(allowedTargets = [AnnotationTarget.PROPERTY])
annotation class Description(val value: String)

Describes a property to the model: of the input class of a Tool, or of the class a model is asked for with ask.

Link copied to clipboard
sealed interface Question

A question to a DecisionModel. Its kind decides the kind of Answer.

Link copied to clipboard
class StateTool<State>(val spec: ToolSpec, val execute: suspend (State, JsonObject) -> ToolOutcome<State>)

A function a model may call that reads the state of the run and changes it: add a line to an order, book a seat, move a piece. What it did is in the state, so a checkpoint holds it and the next node sees it.

Link copied to clipboard
@Serializable
data class TokenUsage(val inputTokens: Int = 0, val outputTokens: Int = 0)

The tokens a call to a ChatModel read (inputTokens) and wrote (outputTokens), or those of several calls added up. TokenUsage() is no tokens, the start of a count:

Link copied to clipboard
class Tool(val spec: ToolSpec, val execute: suspend (JsonObject) -> String)

A function a model may call. The usual way to create one is from a @Serializable class that holds the input, which also gives the model the input's schema:

Link copied to clipboard
@Serializable
data class ToolCall(val id: String, val name: String, val input: JsonObject)

A model's request to run the tool named name with input.

Link copied to clipboard
data class ToolOutcome<out State>(val state: State, val text: String)

What a StateTool did.

Link copied to clipboard
data class ToolSpec(val name: String, val description: String, val inputSchema: JsonObject)

What a model is told about a tool.

Link copied to clipboard
data class TypedResponse<out Answer>(val value: Answer, val message: ChatMessage.Assistant, val usage: TokenUsage? = null)

What ask returns for a ChatRequest.

Properties

Link copied to clipboard

The piece of text a model wrote, when this event is a node's report of one, and null for every other event. toolLoop and chatWithProgress report these. A report from inside a subgraph is read as well.

Functions

Link copied to clipboard
inline suspend fun <Answer> ChatModel.ask(request: ChatRequest, attempts: Int = 2): TypedResponse<Answer>

Returns the model's next message for request as an instance of the @Serializable class Answer, with the message it was read from. Use it to ask for a value at the end of a conversation. See the overload with a prompt for how the model is asked.

inline suspend fun <Answer> ChatModel.ask(prompt: String, system: String? = null, attempts: Int = 2): Answer

Sends prompt as a single user message and returns the answer as an instance of the @Serializable class Answer, for a node that needs a value from the model and not a text.

suspend fun <Answer> ChatModel.ask(serializer: KSerializer<Answer>, request: ChatRequest, attempts: Int = 2): TypedResponse<Answer>

Returns the model's next message for request as a value read with serializer. See the overload with a reified type.

Link copied to clipboard
suspend fun ChatModel.chat(prompt: String, system: String? = null): String

Sends prompt as a single user message and returns the text of the answer, for a node that only needs a piece of text from the model. Call ChatModel.chat with a ChatRequest when you need to know whether the answer was cut off.

Link copied to clipboard

Returns the model's next message for request, like ChatModel.chat, and lets a streamed run watch the model write it. Use it in a node in place of ChatModel.chat:

suspend fun ChatModel.chatWithProgress(prompt: String, system: String? = null): String

Sends prompt as a single user message and returns the text of the answer, like chat with a prompt, and lets a streamed run watch the model write it. See the overload with a ChatRequest.

Link copied to clipboard
inline suspend fun <Option : Enum<Option>> DecisionModel.choose(state: String, instructions: String, describe: (Option) -> String? = { null }): Answer.Choice

Asks which constant of the enum Option fits state. The model sees the names of the constants, and for each one the text that describe returns. Read the constant from the answer with value.

suspend fun DecisionModel.choose(state: String, instructions: String, options: Map<String, String?>): Answer.Choice

Asks which of options fits state, for a node or an edge with one decision to make.

Link copied to clipboard
fun <State> StateGraph<State>.decisionEdge(from: NodeRef, model: DecisionModel, instructions: String, routes: Map<NodeRef, String?>, minConfidence: Double = 0.0, fallback: NodeRef? = null, state: suspend (State) -> String)

Adds a conditional edge from from on which a DecisionModel picks the next node: a router that understands language, at the speed and price of a decision model.

fun <State> StateGraph<State>.decisionEdge(from: String, model: DecisionModel, instructions: String, routes: Map<NodeRef, String?>, minConfidence: Double = 0.0, fallback: NodeRef? = null, state: suspend (State) -> String)

Adds a decision edge from the node named from, usually START. See the overload taking a NodeRef.

Link copied to clipboard

Runs calls in parallel on these tools and returns one result for each call, in the order of the calls.

Link copied to clipboard
suspend fun DecisionModel.isYes(state: String, instructions: String): Answer.YesNo

Asks a yes/no question about state. Read Answer.YesNo.isYes, or compare Answer.YesNo.probability with a line of your own.

Link copied to clipboard

Returns the tool calls of the last assistant message that have no ChatMessage.ToolResult yet.

Link copied to clipboard
suspend fun DecisionModel.score(state: String, instructions: String, levels: List<String>): Answer.Score

Asks for a rating of state on the scale of levels, described from the lowest to the highest.

Link copied to clipboard
inline fun <State, Input> StateTool(name: String, description: String, noinline execute: suspend (State, Input) -> ToolOutcome<State>): StateTool<State>

Creates a StateTool for a graph with the state State, whose input is the @Serializable type Input. The input schema is built from the type as for a Tool. Use StateTool<State, Unit> for a tool that takes no input.

fun <State, Input> StateTool(name: String, description: String, serializer: KSerializer<Input>, execute: suspend (State, Input) -> ToolOutcome<State>): StateTool<State>

Creates a StateTool whose input is read with serializer. See the overload with a reified type.

Link copied to clipboard
inline fun <Input> Tool(name: String, description: String, noinline execute: suspend (Input) -> String): Tool

Creates a Tool whose input is the @Serializable type Input. The input schema is built from the type, with the text of Description annotations as the description of each property.

fun <Input> Tool(name: String, description: String, serializer: KSerializer<Input>, execute: suspend (Input) -> String): Tool

Creates a Tool whose input is read with serializer. See the overload with a reified type.

Link copied to clipboard
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.

Link copied to clipboard
fun <State> StateGraph<State>.toolLoop(model: ChatModel, tools: List<Tool> = emptyList(), messages: (State) -> List<ChatMessage>, append: (State, List<ChatMessage>) -> State, firstMessage: (State) -> String? = null, system: String? = null, then: NodeRef = NodeRef.END, modelNode: String = "model", toolsNode: String = "tools", stateTools: List<StateTool<State>> = emptyList(), inOrder: Boolean = false, countTokens: (State, TokenUsage) -> State? = null, stopWhen: (State) -> Boolean? = null, retry: Retry? = null): NodeRef

Adds the loop of a tool-calling agent to this graph and returns its first node.

Link copied to clipboard

The constant of Option that this answer picked, after a choose with that enum.