---
title: "Custom Agents"
framework: vue
version: "2.1.2"
---

# Custom Agents

The [Default Agents](https://www.ag-grid.com/studio/vue/ai-ax/) cover most dashboard-building tasks, but you can change how the built-in runtime's agents behave: rewrite an agent's instructions, change the tools it can use, or add an agent of your own. You supply agents through the `agents` field on your [Adapter](https://www.ag-grid.com/studio/vue/ai-adapter/).

## Supplying Agents

`agents` is the set of agents the runtime runs. Omit it and you get the defaults. Provide it and you control the set - so include `agStudioDefaultAgents` when you want to keep the built-in agents alongside your own.

```ts
import { agStudioDefaultAgents } from 'ag-studio';
```

```ts
<ag-studio
    :ai="ai"
    /* other studio properties ... */>
</ag-studio>

this.ai = {
    executeTurn,
    agents: [chartBuilder],
    primaryAgent: 'chart-builder',
};
```

`primaryAgent` is the agent a conversation starts from - it defaults to `'lead'`. Set it to one of your own to start there instead. The array above runs a single custom agent; to keep the built-in agents alongside yours, spread `agStudioDefaultAgents` into it (`agents: [...agStudioDefaultAgents, chartBuilder]`).

## Defining an Agent

An agent has a `type`, a `schema` for its parameters, and a `config` factory that returns its behaviour. The factory receives the parameters and returns the agent's name, instructions, tools, and delegation permissions - so an agent's behaviour can vary by input.

```ts
import type { AgAiAgent } from 'ag-studio';

const chartBuilder: AgAiAgent = {
    type: 'chart-builder',
    description: 'Explores the data and builds bar charts.',
    schema: (s) => s.undefined(),
    config: () => ({
        name: 'Chart Builder',
        instructions: (api) => {
            const { tables } = api.getAiContext().schema();
            return `You are a bar-chart specialist for this dashboard.

Voice: always reply in British English, in a warm and concise tone. Open each reply with a one-sentence summary of the action you are about to take.

Build charts with add_widget then configure_widget, using a bar-chart type only. Manage filters with the page and widget filter tools. Explore the data with view_schema and execute_query before building.

Available tables: ${tables.map((t) => t.name).join(', ')}.`;
        },
        tools: [
            { name: 'view_schema' },
            { name: 'execute_query' },
            { name: 'add_widget' },
            { name: 'configure_widget' },
            { name: 'position_widget' },
            { name: 'add_page_filter' },
            { name: 'remove_page_filter' },
            { name: 'add_widget_filter' },
            { name: 'remove_widget_filter' },
        ],
    }),
};
```

### Instructions

`instructions` receives the studio `api`, so an agent can ground itself in the live dashboard - the schema, the widget catalogue, current page state. Retrieve these through `api.getAiContext()`; see [Context](https://www.ag-grid.com/studio/vue/ai-context/) for the full surface. Instructions also shape how the agent *responds* - the `Voice` line above steers its tone and language, so you can give an agent a house style or have it reply in another language.

### Tools

`tools` lists the tools the agent may call, by name - and it is also how you constrain an agent. `chartBuilder` is given the query, widget, and filter tools but not `remove_widget` or the planning tools, so it stays within building bar charts and managing filters. The full set is in the [Built-in Tools Reference](https://www.ag-grid.com/studio/vue/ai-ax#tool-reference).

### Delegation

`delegateAgents` lists the agent types this agent may hand work to. `chartBuilder` runs alone, so it needs none. The built-in Lead delegates to the planning, data, page, and widget agents; to have a coordinator delegate to an agent of your own, supply your own coordinator that lists it in `delegateAgents`.

## Example

The example below runs `chartBuilder` as the only agent. Open the AI panel and ask it to "chart net sales by region" to watch it query the data and build a bar chart - and note the British-English, summary-first voice its instructions give it. Ask for a line chart and it will decline and offer a bar chart instead.

#### Custom Agents

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgStudio } from "ag-studio-vue3";
import { openaiAdapter } from "./shared/openaiAdapter.ts";
import {
  AgAiAgent,
  AgAiAssistant,
  AgDataEngine,
  AgDataSourcesDefinition,
  AgReportState,
  AgStudioAiModule,
  AgStudioApi,
  AgStudioApiReadyEvent,
  AgStudioMode,
  AgStudioModuleRegistry,
  AgStudioProperties,
} from "ag-studio";
import { getMainDemoData } from "./data.ts";

AgStudioModuleRegistry.registerModules([AgStudioAiModule]);

export const AI_API_URL = "https://ai-api.ag-grid.com/api/openai/v1";

export const AI_API_TOKEN = "";

const chartBuilder: AgAiAgent = {
  type: "chart-builder",
  description: "Explores the data and builds bar charts.",
  schema: (s) => s.undefined(),
  config: () => ({
    name: "Chart Builder",
    instructions: (api) => {
      const { tables } = api.getAiContext().schema();
      return `You are a bar-chart specialist for this dashboard. You explore the user's data and build bar charts.

Voice: always reply in British English, in a warm and concise tone. Open each reply with a one-sentence summary of the action you are about to take, then keep any explanation to a sentence or two.

What you do:
- Explore the data with view_schema and execute_query before building anything.
- Build charts with add_widget then configure_widget, and place them with position_widget. Only ever use a bar-chart type: 'bar-chart', 'bar-chart-grouped', 'bar-chart-stacked', or 'bar-chart-stacked-100'. If asked for any other chart type, explain that you build bar charts only and offer the closest bar-chart alternative.
- Manage filters with add_page_filter / remove_page_filter and add_widget_filter / remove_widget_filter.

Available tables: ${tables.map((t) => t.name).join(", ")}.`;
    },
    tools: [
      { name: "view_schema" },
      { name: "execute_query" },
      { name: "view_page" },
      { name: "view_widget" },
      { name: "add_widget" },
      { name: "configure_widget", params: { widgetType: "bar-chart-grouped" } },
      { name: "position_widget" },
      { name: "add_page_filter" },
      { name: "remove_page_filter" },
      { name: "add_widget_filter" },
      { name: "remove_widget_filter" },
    ],
  }),
};

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div style="display: flex; flex-direction: column; height: 100%">
      <ag-studio
        style="width: 100%; height: 100%;"
        class="my-studio-container"
        @api-ready="onApiReady"
        :data="data"
        :mode="mode"
        :initialState="initialState"
        :ai="ai"></ag-studio>
      </div>
        </div>
    `,
  components: {
    "ag-studio": AgStudio,
  },
  setup(props) {
    const studioApi = shallowRef<AgStudioApi | null>(null);
    const data = ref<AgDataSourcesDefinition | AgDataEngine>(
      getMainDemoData("https://www.ag-grid.com/studio/example-assets"),
    );
    const mode = ref<AgStudioMode>("edit");
    const initialState = ref<AgReportState>({
      pages: [{ id: "main", widgets: {}, widgetLayout: {} }],
      selectedPageId: "main",
      panels: {
        filters: { collapsed: true },
        edit: { collapsed: true },
        data: { collapsed: true },
      },
    });
    const ai = ref<AgAiAssistant>({
      ...openaiAdapter({
        endpoint: AI_API_URL,
        key: AI_API_TOKEN,
      }),
      agents: [chartBuilder],
      primaryAgent: "chart-builder",
    });

    const onApiReady = (params: AgStudioApiReadyEvent) => {
      studioApi.value = params.api;
    };

    return {
      studioApi,
      data,
      mode,
      initialState,
      ai,
      onApiReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Custom Agents](https://www.ag-grid.com/studio/examples/ai-custom-agents/ai-custom-agents-example/vue3/)

## Interface Reference

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `type` | `string` |  | Unique identifier for this agent type. |
| `description` | `string` |  | Short description of what this agent does, shown to a delegating agent so it can decide when to hand off. Falls back to type when omitted. |
| `schema` | `Function` |  | Builds the shape that validates this agent's parameters, given the shape builder. Return `s.undefined()` for a param-less agent, or e.g. `s.object({ region: s.string() })` to require parameters. |
| `config` | `Function` |  | Agent configuration. The factory function receives parameters and returns the configuration, allowing dynamic agent behaviour based on input. |

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `name` | `string` |  | Display name for the agent, shown in UI. |
| `icon` | `string` |  | SVG icon string for the agent, rendered in delegate cards. Uses `currentColor` for theme adaptability. |
| `instructions` | `Function` |  | System instructions that guide the AI's behaviour for this agent. |
| `delegateAgents` | `string[]` |  | Agent types this agent can delegate tasks to. Enables hierarchical task decomposition across specialised agents. |
| `tools` | `AgToolRef[]` |  | Tool names available to this agent for performing actions. |
| `defaultToolCalls` | `{ tool: string; args?: Record<string, unknown> }[]` |  | Tools to call automatically before the agent's first turn, their results prepended to the agent's instructions. Each named tool must be in tools. |

## Next Steps

- [Context](https://www.ag-grid.com/studio/vue/ai-context/) - Build agent instructions from live dashboard and data state.
- [Default Agents](https://www.ag-grid.com/studio/vue/ai-ax/) - The built-in agents you are extending or replacing.
