diff --git a/docs.json b/docs.json index b8f20585..75c6dc2c 100644 --- a/docs.json +++ b/docs.json @@ -164,7 +164,8 @@ "guides/ai-agents/ai-writeback", "guides/ai-agents/content-tools", "guides/ai-agents/mcp-servers", - "guides/ai-agents/autopilot" + "guides/ai-agents/autopilot", + "guides/ai-agents/agents-as-code" ] }, "references/integrations/lightdash-mcp", diff --git a/guides/ai-agents.mdx b/guides/ai-agents.mdx index c538085f..a092e2bb 100644 --- a/guides/ai-agents.mdx +++ b/guides/ai-agents.mdx @@ -51,6 +51,9 @@ This guide covers everything you need to know about AI agents in Lightdash: + + + diff --git a/guides/ai-agents/agents-as-code.mdx b/guides/ai-agents/agents-as-code.mdx new file mode 100644 index 00000000..ab061cd3 --- /dev/null +++ b/guides/ai-agents/agents-as-code.mdx @@ -0,0 +1,172 @@ +--- +title: "AI agents as code" +sidebarTitle: "Agents as code" +description: "Download AI agents to YAML, review them in Git, and promote them between projects using the same content-as-code workflow as charts and dashboards." +--- + +You can serialize a project's AI agents to YAML with the Lightdash CLI, keep them under version control, and promote them between environments — preview, staging, production — using the standard `lightdash download` / `lightdash upload` flow. + +Use agents as code when you want to: + +- Review agent instructions, tags, and model settings in pull requests before they reach production +- Copy a working agent from one project to another (for example, from a preview into production) without recreating it in the UI +- Roll agent config back to a known-good version using Git history +- Bootstrap new projects with the same set of agents you use elsewhere + +Agent config as code is **opt-in**. A bare `lightdash download` does not include agents — you have to ask for them with `--include-agents` or `--agents`. + + +This is part of the same content-as-code system as [dashboards as code](/guides/developer/dashboards-as-code). The same disposable-vs-Git-managed tradeoff and CI patterns apply. + + +## On-disk layout + +Agent files live under `lightdash/ai-agents/` next to your `charts/` and `dashboards/` folders. Each agent is a single `.yml` file named after its slug: + +```text +lightdash/ +├── ai-agents/ +│ ├── orders-support-agent.yml +│ └── revenue-analyst.yml +├── charts/ +└── dashboards/ +``` + +`lightdash upload` automatically picks up every `.yml` (or `.yaml`) file in `lightdash/ai-agents/` and syncs it to the [selected project](/references/lightdash-cli#lightdash-config-set-project). + +## Downloading agents + +Use one of the two flags below to include agents in a download. Neither is set by default. + +Download every AI agent in the project (paginated automatically by the CLI): + +```bash +lightdash download --include-agents +``` + +Download only specific agents by slug or UUID: + +```bash +lightdash download --agents orders-support-agent revenue-analyst +``` + +You can combine agent flags with the usual `--charts`, `--dashboards`, `--project`, and `-p / --path` flags on [`lightdash download`](/references/lightdash-cli#lightdash-download). + +## Uploading agents + +`lightdash upload` uploads every agent file in `lightdash/ai-agents/` by default. Uploads are **idempotent**: the server creates missing agents, updates existing agents by slug, and leaves unchanged agents alone. + +Upload every agent along with charts and dashboards: + +```bash +lightdash upload +``` + +Upload only specific agents by slug: + +```bash +lightdash upload --agents orders-support-agent +``` + +Skip agent uploads entirely, even when files exist under `lightdash/ai-agents/`: + +```bash +lightdash upload --skip-agents +``` + + +Unlike charts and dashboards, you do **not** need `--force` to create a new agent. Uploading a file whose `slug` does not exist in the target project creates the agent; changing the `slug` in an existing file creates a new agent under the new slug (the old one is not deleted). + + +### Exit codes and validation + +The CLI validates each agent file before uploading. Invalid YAML, missing required fields, wrong `contentType`, or duplicate slugs across files cause `lightdash upload` to exit with a non-zero status, which is what you want in CI so bad config fails the build. + +## YAML schema + +Every agent file uses the following top-level shape. The schema is versioned independently from the runtime engine — `version` describes the as-code file format, and `agentVersion` records which runtime version the agent uses. + +```yaml lightdash/ai-agents/orders-support-agent.yml +contentType: ai_agent +version: 1 +agentVersion: 2 +slug: orders-support-agent +name: Orders Support Agent +description: Answers questions about orders, fulfillment, and refunds. +imageUrl: null +instruction: | + You are a support analyst for the ecommerce team. Use the orders and + shipments explores to answer questions about order status, refunds, and + fulfillment SLAs. Always report totals in GBP. +tags: + - ai + - orders +enableDataAccess: true +enableSelfImprovement: true +enableContentTools: false +enableUserContext: true +modelConfig: + modelName: gpt-4o + modelProvider: openai + reasoning: false +``` + +### Field reference + +| Field | Type | Description | +| --- | --- | --- | +| `contentType` | string | Always `ai_agent`. The CLI refuses to upload files with any other value. | +| `version` | number | Schema version of the file itself. Currently `1`. | +| `agentVersion` | `1` \| `2` | Runtime version of the agent. Both v1 and v2 round-trip through download and upload. | +| `slug` | string | Stable identifier used to match against agents in the target project. Changing the slug creates a new agent on upload. | +| `name` | string | Human-readable name shown in the UI. | +| `description` | string \| null | Short description. | +| `imageUrl` | string \| null | URL for the agent's avatar. Uploaded-avatar provenance is preserved across environments. | +| `instruction` | string \| null | The agent's system prompt / instructions. See [getting started](/guides/ai-agents/getting-started#instructions) for guidance on what to include. | +| `tags` | string[] \| null | Semantic tags used for [data access control](/guides/ai-agents/data-access#limiting-access-to-specific-explores-and-fields). | +| `enableDataAccess` | boolean | Whether the agent can execute queries and read actual data. See [data access](/guides/ai-agents/data-access). | +| `enableSelfImprovement` | boolean | Whether the agent captures corrections into [agent memory](/guides/ai-agents/agent-memory). | +| `enableContentTools` | boolean | Whether the agent can create and edit charts and dashboards. See [creating & editing content](/guides/ai-agents/content-tools). | +| `enableUserContext` | boolean | Whether the agent receives the asking user's identity for [personalized answers](/guides/ai-agents/data-access#personalizing-answers-to-who-is-asking). | +| `modelConfig` | object \| null | Default model settings: `modelName`, `modelProvider`, and optional `reasoning` flag. When `null`, the agent inherits the [organization default](/guides/ai-agents/getting-started#set-an-organization-default-ai-model). | + +## What is not versioned + +Some pieces of an agent are runtime state and are deliberately kept out of the YAML file — they stay in the target environment and are preserved across create/update/no-op uploads: + +- **Conversations and threads.** Chat history is runtime state and never written to YAML. Uploading a change to an agent does not touch existing threads. +- **User and group access lists.** Access control is project-specific and stays managed in the target environment. See [user and group access](/guides/ai-agents/getting-started#user-and-group-access-optional). +- **Slack integrations.** Slack channel bindings are per-environment and are not serialized. +- **MCP server references.** [MCP server](/guides/ai-agents/mcp-servers) references stay in the target project. +- **Uploaded knowledge documents.** Uploaded [documents](/guides/ai-agents/getting-started#knowledge-documents-optional) are preserved across upload but are not written into the YAML file itself. + +This split lets you promote agent behavior (instructions, tags, model config, capability flags) through Git while still letting each environment own the things that don't make sense to copy — production Slack channels, per-project MCP servers, per-environment access lists. + +## Lifecycle examples + +Assuming a file at `lightdash/ai-agents/orders-support-agent.yml`: + +- **Create.** The target project has no agent with slug `orders-support-agent`. `lightdash upload` creates it. +- **Update.** The target project already has `orders-support-agent`. Editing `instruction` or `tags` in the file and running `lightdash upload` updates the existing agent in place. +- **No-op.** Nothing has changed since the last upload. The CLI reports the agent as skipped and makes no API call. +- **Rename by slug.** Changing `slug: orders-support-agent` to `slug: orders-support-agent-v2` and uploading creates a new agent under the new slug. The original agent is untouched. +- **Per-project isolation.** Uploading with `--project ` only affects that project — the same slug in different projects refers to different agents. + +## API + +The CLI is a thin wrapper around two permission-gated project endpoints: + +- **`GET /api/v1/projects/{projectUuid}/aiAgents/code`** — paginated download of agents as code. Accepts repeated `ids` query params (slug or UUID) to filter, and an `offset` for pagination. +- **`POST /api/v1/projects/{projectUuid}/aiAgents/code`** — idempotent create-or-update by slug for one or more agents. Accepts a `force` query flag. Returns a summary of `created`, `updated`, `unchanged`, and `deleted` slugs. + +Both endpoints require project-level permission to manage AI agents. See the [API reference](/api-reference/v1/introduction) for the full request and response schema. + +## CI/CD + +Because upload is idempotent and returns a non-zero exit code on invalid files, agents as code fits the same CI patterns as [Git-managed dashboards](/guides/developer/dashboards-as-code#git-managed-dashboards): + +1. Store `lightdash/ai-agents/` in Git. +2. On PR, run `lightdash upload --skip-charts --skip-dashboards --agents ` against a [preview project](/guides/developer/preview-projects) to sanity-check the change. +3. On merge to `main`, run `lightdash upload` against production. + +Lock down agent editing in the UI (via role permissions) if you want the YAML files to be the definitive source of truth for agent config. diff --git a/guides/developer/dashboards-as-code.mdx b/guides/developer/dashboards-as-code.mdx index c5fee1a3..00fbdda7 100644 --- a/guides/developer/dashboards-as-code.mdx +++ b/guides/developer/dashboards-as-code.mdx @@ -899,6 +899,11 @@ And the matching tile entry on a dashboard: tileSlug: orders-by-status ``` +## AI agents as code + +AI agent configuration can also be managed as code and promoted between projects with the same `lightdash download` / `lightdash upload` workflow used for charts and dashboards. This is useful for keeping agent instructions and tags under review in Git, and for copying a working agent from a preview or staging project into production. + +Agent config as code is **opt-in**: a bare `lightdash download` does not include agents. See [AI agents as code](/guides/ai-agents/agents-as-code) for the full guide, including the YAML schema, CLI flags, and what runtime state stays in the target environment. ## Custom roles as code [Custom roles](/references/workspace/custom-roles) are also managed as code. Unlike charts and dashboards, custom roles are **organization-scoped** rather than project-scoped, so downloading and uploading them uses the `--organization` mode of `lightdash download` and `lightdash upload` and requires an organization admin. diff --git a/references/lightdash-cli.mdx b/references/lightdash-cli.mdx index 061d1271..1457e935 100644 --- a/references/lightdash-cli.mdx +++ b/references/lightdash-cli.mdx @@ -709,6 +709,11 @@ You can make changes to the code and upload these changes back to your Lightdash - `--skip-dashboards` - (default: false) - skip downloading dashboards +- `--agents ` + - opt-in flag to also download specific AI agents as code. Pass one or more agent slugs or UUIDs. Files are written to `lightdash/ai-agents/.yml`. See [AI agents as code](/guides/ai-agents/agents-as-code) for the YAML schema and lifecycle rules. +- `--include-agents` + - (default: false) + - opt-in flag to download every AI agent in the project as code. The endpoint is paginated, so the CLI walks all pages automatically. Agent files are written to `lightdash/ai-agents/`. Bare `lightdash download` does not include agents. - `--organization` - (default: false) - switch to organization mode and download organization-scoped content (currently [custom roles](/guides/developer/dashboards-as-code#custom-roles-as-code)) instead of project content. Files are written to `lightdash/custom-roles/.yml`. Requires organization admin permissions. Cannot be combined with project-content flags such as `--charts`, `--dashboards`, `--project`, or `--nested`. @@ -777,6 +782,16 @@ Download just one data app and nothing else. lightdash download --apps-only --apps 8f2b1c4d-1111-2222-3333-444455556666 ``` +Download every AI agent in the project alongside charts and dashboards. + +```bash +lightdash download --include-agents +``` + +Download only a specific AI agent by slug (or UUID). + +```bash +lightdash download --agents orders-support-agent Download all charts and dashboards, plus every virtual view in the project. ```bash @@ -841,6 +856,11 @@ If there have been changes made to a chart or dashboard in the application that - `--create-new` - (default: false) - always create a new data app from the uploaded source instead of appending a new version to the app referenced by `lightdash-app.yml`. Combine with `--apps` and `--project` when copying an app to a different project or instance in a non-interactive shell. +- `--agents ` + - upload only the AI agent files matching these slugs from `lightdash/ai-agents/`. Omit to upload every agent file in that folder. Upload is idempotent — the server creates missing agents, updates existing agents by slug, and leaves unchanged agents alone. See [AI agents as code](/guides/ai-agents/agents-as-code). +- `--skip-agents` + - (default: false) + - skip uploading AI agents even when `lightdash/ai-agents/` contains files. Use this to keep an agents folder in your repo without pushing changes on every `lightdash upload`. - `--organization` - (default: false) - switch to organization mode and upload organization-scoped content (currently [custom roles](/guides/developer/dashboards-as-code#custom-roles-as-code)) instead of project content. Reads YAML files from `lightdash/custom-roles/` and upserts each role by name — creating, updating, or reporting no change per file. Requires organization admin permissions. Cannot be combined with project-content flags such as `--charts`, `--dashboards`, `--project`, or `--force`. Uploads never delete roles. @@ -921,6 +941,16 @@ Copy a data app to a different project as a brand-new app (non-interactive). lightdash upload --apps --project 21eef0b9-5bae-40f3-851e-9554588e71a6 --create-new ``` +Upload every AI agent file under `lightdash/ai-agents/` (creates missing agents, updates existing ones by slug). + +```bash +lightdash upload +``` + +Upload only a specific AI agent by slug. + +```bash +lightdash upload --agents orders-support-agent Upload every custom role in `lightdash/custom-roles/` back to the organization (requires org admin). ```bash