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

# Agents

> What an agent is, what it contains, how the compiler turns your project into one, and where end users meet it

An agent is the unit an end user talks to: one persona, one model, and every skill, other primitive, and connection you register on it. It exists so that everything the agent can do is declared in one place, tested as one thing, and released as one thing.

## How an agent is assembled

In a project created with `lua init`, the agent is a single `new LuaAgent({ … })` in the entry file, `src/index.ts`. Two fields are required: `name`, the identifier you'll see in the CLI and the admin dashboard, and [`persona`](/concepts/persona), the text that tells the model who the agent is and how it behaves. Everything else is optional and falls into two groups.

The first group is the primitives the agent owns, each an array on the config: `skills` (your [tools](/concepts/skills-and-tools)), `webhooks`, `triggers`, `jobs`, `workflows`, `preProcessors` and `postProcessors`, `mcpServers`, `devices` and `deviceTriggers`, and `voices`. The second group is agent-wide settings: `model` and `modelSettings` (which [model](/concepts/models) answers and how), `description` (the one-line capability summary a [Space](/concepts/spaces) uses for routing), `batching`, [`governance`](/concepts/governance) (rules that block a tool call or hold it for a person's approval), and `browser`.

```ts src/index.ts theme={null}
import { LuaAgent } from 'lua-cli';
import ordersSkill from './skills/orders.skill';
import dailyDigest from './jobs/DailyDigestJob';

export default new LuaAgent({
  name: 'acme-support',
  persona: 'You are the support agent for Acme. Confirm the order number before acting.',
  skills: [ordersSkill],
  jobs: [dailyDigest],
});
```

`lua compile` starts at the agent and follows each array through your imports. A skill, job, or webhook is compiled, pushed, and versioned only if the agent references it; a file that is never imported into the agent is never bundled, however well-formed it is. The compiler looks for the agent in `index.ts`, `src/index.ts`, `agent.ts`, `src/agent.ts`, `main.ts`, or `src/main.ts`, in that order. Server-side IDs and versions for every registered primitive are written to `lua.skill.yaml`, which the CLI owns; you don't edit it.

Some things the agent has are configured on the server rather than in your code: [knowledge and features](/concepts/knowledge-and-features) (uploaded documents, web search, inquiry forms), [channels](/concepts/channels) (where end users reach it), [environment variables](/concepts/environments), and connected [integrations](/concepts/integrations). An operator changes knowledge, features, channels, and integrations from the admin dashboard without touching code (the CLI has `lua features`, `lua resources`, `lua channels`, and `lua integrations` for the same); environment variables are set with `lua env production`, which the admin dashboard doesn't edit.

## Sandbox, production, and the hosted chat page

Every agent has two environments. The sandbox is where `lua chat` uploads your local skills, processors, and persona as temporary sandbox versions and the platform runs them, without a `lua push`; production is what end users talk to on every channel. Code reaches production through [releases and versions](/concepts/releases-and-versions): `lua push` uploads a version, `lua version create` snapshots the agent, and `lua version promote <n>` makes it live; a pushed persona is the exception and is served from the agent's next message. The [environments](/concepts/environments) page describes what the two share and what differs.

Every agent also has a hosted chat page at `https://heylua.ai/agent?agentId=<agent-id>`, where `<agent-id>` is the `agentId` in `lua.skill.yaml`. It needs no embedding or code and is the quickest way to share the agent with a teammate or a client before you connect a channel. Pass a Space's ID instead to talk to the Space.&#x20;

## An agent and a Space

An agent answers for itself. A Space is a supervisor, created in the admin dashboard, that sits in front of several agents and routes each message to one of them using the agents' `description` fields. Build one agent until you have a reason not to; a Space is for when distinct personas must coexist behind one entry point. Agents can also call each other from code with `Agents.invoke`, which runs a full turn on the target agent.

## When to split an agent

* Two audiences need different personas (customers and staff): two agents.
* Some data must stay behind a separate boundary (payments, medical records): a separate agent, with `governance` on the sensitive one.
* Cost differs sharply by task: a cheap front-line agent that hands off to a specialist with `Agents.invoke`.
* You want tidier code: don't split. Skills are the unit of code organization, and one agent can hold many.

## Limits

* `name` and `persona` are required; an object-form persona must set at least one of `base`, `voice`, `text`, or construction throws `Agent persona object must have at least one of: base, voice, text`.
* `modelSettings` is validated when the agent is constructed: `temperature` 0–2, `topP` 0–1, `maxOutputTokens` at least 1, `reasoning.effort` one of `off`, `minimal`, `low`, `medium`, `high`, `max`.
* One `LuaAgent` per project. The compiler stops at the first entry file it finds.
* Primitives not reachable from the agent's arrays are not compiled or pushed.

## Next steps

<Columns cols={2}>
  <Card title="Build an agent" href="/get-started/build-an-agent">A support agent from first tool to release.</Card>
  <Card title="Project structure" href="/get-started/project-structure">What `lua init` creates and which files you edit.</Card>
  <Card title="LuaAgent reference" href="/reference/sdk/luaagent">Every field and its type.</Card>
  <Card title="Releases and versions" href="/concepts/releases-and-versions">How an agent version goes live and rolls back.</Card>
</Columns>
