Dagger.LLM (dagger v1.0.0-beta.19)

Copy Markdown View Source

A conversation with a large language model (LLM): queue prompts, expose tools, and step the model until it completes its turn.

Summary

Functions

Reconstruct a spawned agent from its runtime handle.

Discover every artifact this conversation can address, as one selection, without evaluating their values.

Run expertise on this conversation, passing it through each function in order, and record it in expertise.

estimated number of tokens currently occupying the context window; unlike tokenUsage this is not cumulative over the session

The model's total context window in tokens, or null if unknown (e.g. a local or uncatalogued model).

Expertise composed into this conversation, in order.

Fork the conversation, so that otherwise-identical follow-ups evaluate independently instead of deduplicating to a single cached result.

Report whether anything is queued to send to the model: an unsent prompt or unevaluated tool results. When true, another step will do work; when false, the turn is complete.

A unique identifier for this LLM.

The text of the model's most recent reply.

Send the queued prompt and step the model against the available tools, until it ends its turn: a reply with no tool calls and nothing left queued.

The full message history, as structured messages.

The model the conversation is running against, after resolving any configured default.

The provider serving the model, e.g. "anthropic", "openai", "google", or "local".

The reasoning effort in use, e.g. "low", "medium", or "high". Empty or "none" when reasoning is disabled.

The skills visible to the model, exactly as the ListSkills tool serves them: engine-embedded skills, skills installed with withSkills, and skills discovered in the workspace.

Spawn the conversation as an agent: a startable, addressable evaluation loop seeded with this conversation's state, tools, and workspace.

Advance the conversation by a single step: send the queued prompt or tool results to the model, evaluate any tool calls it makes, and queue their results. Use loop to step until the model ends its turn.

Force evaluation of the conversation's pending operations (prompts, steps, loops) in the engine.

The cumulative token usage, summed across every API call in the conversation.

Render documentation for the tools currently exposed to the model.

The message history rendered as a plain-text transcript, suitable for feeding back to an LLM (e.g. for summarization).

Queue one user message containing ordered text and media blocks.

Queue an image, audio, or PDF file as one user message. Media bytes are stored in the conversation.

Add an external MCP server to the LLM

Change the model for the rest of the conversation. The message history is preserved; the new model takes effect on the next step.

Queue a user prompt, to be sent to the model on the next step or loop.

Queue a file's contents as a user prompt, like withPrompt.

Change the reasoning effort for the rest of the conversation, overriding any configured default. The message history is preserved; the new effort takes effect on the next step.

Append an assistant response to the message history without calling the model, e.g. to reconstruct a conversation from another source.

Install skills from a directory, adding them to the skills the model discovers with ListSkills and reads with ReadSkill. Each skill is a directory containing a SKILL.md with name and description frontmatter, discovered anywhere in the tree. Installed skills take precedence over skills discovered in the workspace, but cannot shadow the engine's built-in skills.

Switch to the configured small model for the current provider, or that provider's recommended default. The message history is preserved; unknown providers without a small-model configuration keep their current model.

Add a system prompt, instructing the model across the whole conversation.

Append the result of a tool call to the message history.

Expose an object's methods as tools. Every eligible method of the bound object becomes a tool; a tool that returns this object's own type replaces it as the new state. Repeatable to bind several objects.

Bind the LLM to a workspace, exposing its modules as tools exactly as the Dagger CLI would serve them for that workspace.

Disable the default system prompt

Clear the message history, keeping only the system prompts.

Clear the user-added system prompts, keeping only the default system prompt.

Return the workspace the LLM is bound to.

Types

t()

@type t() :: %Dagger.LLM{client: term(), query_builder: term()}

Functions

agent(llm, handle, name)

@spec agent(t(), String.t(), String.t()) :: Dagger.Agent.t()

Reconstruct a spawned agent from its runtime handle.

This is the lookup spawn pins its result's identity through: the returned handle's ID is an honest, replayable chain denoting the one instance the spawn minted. It never creates an instance itself.

Experimental

"Agent APIs are likely to change."

artifacts(llm, optional_args \\ [])

@spec artifacts(t(), [{:include, [String.t()]}]) :: Dagger.Artifacts.t()

Discover every artifact this conversation can address, as one selection, without evaluating their values.

Tool objects bound with withTools contribute their modules' artifacts, rooted at their current values: evaluating one reads the live state of the bound tools, not a fresh construction. If a module's main object is bound, only its tree is included; otherwise each bound object of that module contributes its own tree. Addresses start with the module name. These artifacts have no workspace of their own: they evaluate in the LLM's bound workspace, if any, whoever evaluates them.

The workspace part is the artifacts of the workspace bound with withWorkspace, as returned by Workspace.artifacts; an LLM with no bound workspace has none. A workspace module with the same name as a module with bound tool objects is omitted: the bound tools shadow it. Unless they are only a plain construction of the module, which has no state of its own: then the workspace module's artifacts are kept instead.

Tool arguments that take an address resolve it here: a DAG address to one object, or, for Artifacts and Artifact arguments, a selection filtered like filterUri.

Experimental

"Agent APIs are likely to change."

compose(llm, expertise)

@spec compose(t(), [String.t()]) :: t()

Run expertise on this conversation, passing it through each function in order, and record it in expertise.

Composing an entry that is already recorded refreshes its module: the module's contributions are cleared, all of its recorded entries run again, and compatible tool state is kept. Other contributions are untouched.

Agent arguments receive the agent that owns this conversation. Without one, entries requiring an Agent are skipped.

context_tokens(llm)

@spec context_tokens(t()) :: {:ok, integer()} | {:error, term()}

estimated number of tokens currently occupying the context window; unlike tokenUsage this is not cumulative over the session

context_window(llm)

@spec context_window(t()) :: {:ok, integer() | nil} | {:error, term()}

The model's total context window in tokens, or null if unknown (e.g. a local or uncatalogued model).

expertise(llm)

@spec expertise(t()) :: {:ok, [Dagger.Expertise.t()]} | {:error, term()}

Expertise composed into this conversation, in order.

fork(llm, label)

@spec fork(t(), String.t()) :: t()

Fork the conversation, so that otherwise-identical follow-ups evaluate independently instead of deduplicating to a single cached result.

has_pending(llm)

@spec has_pending(t()) :: {:ok, boolean()} | {:error, term()}

Report whether anything is queued to send to the model: an unsent prompt or unevaluated tool results. When true, another step will do work; when false, the turn is complete.

id(llm)

@spec id(t()) :: {:ok, String.t()} | {:error, term()}

A unique identifier for this LLM.

last_reply(llm)

@spec last_reply(t()) :: {:ok, String.t()} | {:error, term()}

The text of the model's most recent reply.

loop(llm, optional_args \\ [])

@spec loop(t(), max_steps: integer() | nil, max_tokens: integer() | nil) :: t()

Send the queued prompt and step the model against the available tools, until it ends its turn: a reply with no tool calls and nothing left queued.

messages(llm)

@spec messages(t()) :: {:ok, [Dagger.LLMMessage.t()]} | {:error, term()}

The full message history, as structured messages.

model(llm)

@spec model(t()) :: {:ok, String.t()} | {:error, term()}

The model the conversation is running against, after resolving any configured default.

provider(llm)

@spec provider(t()) :: {:ok, String.t()} | {:error, term()}

The provider serving the model, e.g. "anthropic", "openai", "google", or "local".

reasoning_effort(llm)

@spec reasoning_effort(t()) :: {:ok, String.t()} | {:error, term()}

The reasoning effort in use, e.g. "low", "medium", or "high". Empty or "none" when reasoning is disabled.

skills(llm)

@spec skills(t()) :: {:ok, [Dagger.LLMSkill.t()]} | {:error, term()}

The skills visible to the model, exactly as the ListSkills tool serves them: engine-embedded skills, skills installed with withSkills, and skills discovered in the workspace.

spawn(llm, optional_args \\ [])

@spec spawn(t(),
  expertise: [Dagger.Expertise.t()],
  name: String.t() | nil,
  handle: String.t() | nil,
  state: Dagger.AgentState.t() | nil,
  parent_handle: String.t() | nil,
  error: String.t() | nil
) :: {:ok, Dagger.Agent.t()} | {:error, term()}

Spawn the conversation as an agent: a startable, addressable evaluation loop seeded with this conversation's state, tools, and workspace.

Every spawn mints a unique agent instance — two spawns of an identical conversation are two distinct agents, like two calls to a process spawn. The result is pinned to the instance (via the agent lookup field), so re-loading its ID re-addresses the same agent from any request in the session.

The loop is not started: the agent spends nothing until it is prompted or resumed, and any input pending on the conversation is stepped then.

With a handle, spawn restores an instance instead of minting one: this conversation becomes the committed history of the agent that handle names, so prompting it continues where it left off — rebuild a conversation's ID from a trace, load it, and spawn it under the handle it belonged to. Fails if that instance already has a runtime entry in this session: a restore must happen before anything else addresses the instance, since by then it may have stepped.

Experimental

"Agent APIs are likely to change."

step(llm, optional_args \\ [])

@spec step(t(), [{:max_tokens, integer() | nil}]) :: t()

Advance the conversation by a single step: send the queued prompt or tool results to the model, evaluate any tool calls it makes, and queue their results. Use loop to step until the model ends its turn.

sync(llm)

@spec sync(t()) :: {:ok, t()} | {:error, term()}

Force evaluation of the conversation's pending operations (prompts, steps, loops) in the engine.

token_usage(llm)

@spec token_usage(t()) :: Dagger.LLMTokenUsage.t()

The cumulative token usage, summed across every API call in the conversation.

tools(llm)

@spec tools(t()) :: {:ok, String.t()} | {:error, term()}

Render documentation for the tools currently exposed to the model.

transcript(llm)

@spec transcript(t()) :: {:ok, String.t()} | {:error, term()}

The message history rendered as a plain-text transcript, suitable for feeding back to an LLM (e.g. for summarization).

with_content(llm, content, optional_args \\ [])

@spec with_content(t(), [Dagger.LLMContentBlockInput.t()], [
  {:origin, Dagger.LLMMessageOriginInput.t() | nil}
]) :: t()

Queue one user message containing ordered text and media blocks.

with_content_file(llm, file, optional_args \\ [])

@spec with_content_file(t(), Dagger.File.t(), [{:mime_type, String.t() | nil}]) :: t()

Queue an image, audio, or PDF file as one user message. Media bytes are stored in the conversation.

with_mcp_server(llm, name, service)

@spec with_mcp_server(t(), String.t(), Dagger.Service.t()) :: t()

Add an external MCP server to the LLM

with_model(llm, model, optional_args \\ [])

@spec with_model(t(), String.t(), [{:provider, String.t() | nil}]) :: t()

Change the model for the rest of the conversation. The message history is preserved; the new model takes effect on the next step.

with_prompt(llm, prompt, optional_args \\ [])

@spec with_prompt(t(), String.t(), [{:origin, Dagger.LLMMessageOriginInput.t() | nil}]) ::
  t()

Queue a user prompt, to be sent to the model on the next step or loop.

with_prompt_file(llm, file)

@spec with_prompt_file(t(), Dagger.File.t()) :: t()

Queue a file's contents as a user prompt, like withPrompt.

with_reasoning_effort(llm, effort)

@spec with_reasoning_effort(t(), String.t()) :: t()

Change the reasoning effort for the rest of the conversation, overriding any configured default. The message history is preserved; the new effort takes effect on the next step.

with_response(llm, content, optional_args \\ [])

@spec with_response(t(), [Dagger.LLMContentBlockInput.t()],
  input_tokens: integer() | nil,
  output_tokens: integer() | nil,
  cached_token_reads: integer() | nil,
  cached_token_writes: integer() | nil,
  total_tokens: integer() | nil
) :: t()

Append an assistant response to the message history without calling the model, e.g. to reconstruct a conversation from another source.

with_skills(llm, directory)

@spec with_skills(t(), Dagger.Directory.t()) :: t()

Install skills from a directory, adding them to the skills the model discovers with ListSkills and reads with ReadSkill. Each skill is a directory containing a SKILL.md with name and description frontmatter, discovered anywhere in the tree. Installed skills take precedence over skills discovered in the workspace, but cannot shadow the engine's built-in skills.

with_small_model(llm)

@spec with_small_model(t()) :: t()

Switch to the configured small model for the current provider, or that provider's recommended default. The message history is preserved; unknown providers without a small-model configuration keep their current model.

with_system_prompt(llm, prompt)

@spec with_system_prompt(t(), String.t()) :: t()

Add a system prompt, instructing the model across the whole conversation.

with_tool_result(llm, call_id, content, errored, optional_args \\ [])

@spec with_tool_result(t(), String.t(), String.t(), boolean(), [
  {:blocks, [Dagger.LLMContentBlockInput.t()]}
]) :: t()

Append the result of a tool call to the message history.

with_tools(llm, object, optional_args \\ [])

@spec with_tools(t(), Dagger.Node.t(), except: [String.t()], version: integer() | nil) ::
  t()

Expose an object's methods as tools. Every eligible method of the bound object becomes a tool; a tool that returns this object's own type replaces it as the new state. Repeatable to bind several objects.

with_workspace(llm, workspace)

@spec with_workspace(t(), Dagger.Workspace.t()) :: t()

Bind the LLM to a workspace, exposing its modules as tools exactly as the Dagger CLI would serve them for that workspace.

without_default_system_prompt(llm)

@spec without_default_system_prompt(t()) :: t()

Disable the default system prompt

without_message_history(llm)

@spec without_message_history(t()) :: t()

Clear the message history, keeping only the system prompts.

without_system_prompts(llm)

@spec without_system_prompts(t()) :: t()

Clear the user-added system prompts, keeping only the default system prompt.

workspace(llm)

@spec workspace(t()) :: Dagger.Workspace.t()

Return the workspace the LLM is bound to.