> ## Documentation Index
> Fetch the complete documentation index at: https://docs.guild.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# LLM agents

> Build prompt-driven agents that use an LLM to accomplish tasks.

<iframe src="https://www.youtube.com/embed/FkZMWrVF52U" title="YouTube video player" frameborder="0" className="w-full aspect-video rounded-xl" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen />

An `llmAgent` pairs a system prompt with a tool set. You define what the agent knows and what it can do — the LLM figures out how to do it.

This is the simplest way to build a Guild agent. No TypeScript logic required — just a prompt and tools.

## Example

```typescript theme={null}
import { guildTools, llmAgent } from "@guildai/agents-sdk"
import { gitHubTools } from "@guildai-services/guildai~github"

const systemPrompt = `
You are a code review assistant.

When given a pull request, retrieve the latest changes
using the GitHub tools and provide helpful feedback.
`

export default llmAgent({
  description: "Reviews pull requests and provides feedback.",
  tools: { ...gitHubTools, ...guildTools },
  systemPrompt,
})
```

<Note>
  The `description` field is optional and deprecated as of `@guildai/agents-sdk` 0.4.0. Guild generates the agent's published description automatically from its code, so setting `description` no longer affects the published description.
</Note>

## Input and output

Every `llmAgent` uses the same fixed schemas:

```typescript theme={null}
// Input: the initial prompt with task details
type Input = {
  type: "text"
  text: string
  attachments?: Attachment[]
}

// Output: the agent's final response
type Output = { type: "text"; text: string }
```

### Attachments

Pass images or PDFs alongside a turn through the optional `attachments` array. Each attachment carries inline base64 data:

```typescript theme={null}
type Attachment = {
  type: "image" | "file" // "image" for images, "file" for PDFs
  mediaType: string // MIME type, e.g. "image/png" or "application/pdf"
  data: string // base64-encoded file contents
}
```

`llmAgent` converts each attachment into the matching LLM content part — `ImagePart` for images and `FilePart` for files — and includes it in the user message sent to the model. Attachments are preserved when the agent resumes in a multi-turn session.

## Execution modes

`llmAgent` supports two modes:

<ParamField body="mode" default="'one-shot'" type="'one-shot' | 'multi-turn'">
  * `"one-shot"` — The agent processes the input, returns a single response, then terminates.
  * `"multi-turn"` — The agent continues interacting with the user until it calls the `__submit__` tool to signal task completion.
</ParamField>

```typescript theme={null}
export default llmAgent({
  description: "An agent that can have back-and-forth conversations.",
  tools: {},
  systemPrompt:
    "Help users interactively. Continue asking questions until you have all the information you need.",
  mode: "multi-turn",
})
```

### The `__submit__` tool

In `"multi-turn"` mode, the runtime injects a `__submit__` tool that the LLM must call to end the session. You do not declare it in your `tools` set.

* **Purpose** — Signals that the agent is done. The value the LLM passes to `__submit__` becomes the agent's final output. Earlier turns in the session are not returned to the caller.
* **Parallel calls** — `__submit__` must **not** be called in the same turn as any other tool. The runtime injects this rule into the system prompt; repeat it in your own `systemPrompt` if the model tries to submit while still calling tools.
* **Completion** — Until the LLM calls `__submit__`, the session stays open for follow-up messages.

## Tool recommendations

* `ui_notify` is wired internally so progress notifications (`task.ui.notify()`) work, but it is hidden from the model unless you explicitly add `ui_notify` to the agent's `tools`. Add `userInterfaceTools` if the agent needs `ui_prompt` or `ui_ping`.
* Include `guildTools` if the agent uses tools that require authorization (e.g., GitHub access), so it can request credentials when needed.

## Selecting specific tools

Use `pick` to include only the tools you need. See [Selecting specific tools](/sdk/tools#selecting-specific-tools) in the SDK reference.

## LLM preferences

By default, Guild resolves the provider and model from the [workspace owner's LLM settings](/platform/llm-settings). An `llmAgent` can express an ordered list of preferred providers — and, optionally, models — with `llmPreferences`:

```typescript theme={null}
export default llmAgent({
  description: "Reviews pull requests and provides feedback.",
  tools: { ...gitHubTools, ...guildTools },
  systemPrompt,
  llmPreferences: [
    { provider: "anthropic", model: "claude-opus-4-5" },
    { provider: "openai" },
  ],
})
```

Earlier entries take priority over later ones. Omit `model` to let the server choose a model from the matching policy.

Preferences are **hints**, not overrides: the account's [model policies](/platform/llm-settings#model-policies) have the final say, so a preferred model is used only if a policy allows it. Guild honors the list only when the account brings its own keys (BYOK) and server-side model selection is enabled; otherwise it is ignored and the model is selected from policy.

For coded and self-managed agents, pass `llmPreferences` per call to `task.llm.generateText` instead. See [LLM preferences](/guide/llms#llm-preferences) for that form and the full `LLMPreference` shape.

## When to use LLM agents

| Situation                                   | Use `llmAgent`?                              |
| ------------------------------------------- | -------------------------------------------- |
| Task is expressible as a prompt + tools     | Yes                                          |
| You need deterministic, repeatable behavior | No — use [coded agents](/guide/coded-agents) |
| You want to minimize LLM token costs        | No — use [coded agents](/guide/coded-agents) |
