---
title: "Toolkit"
framework: angular
version: "2.1.2"
---

# Toolkit

The Toolkit exposes Studio's built-in actions as standalone, framework-agnostic units, so you can drive the AI loop in your own runtime instead of the built-in one. A custom runtime needs no agents - you decide what the model can do by choosing which commands to expose as tools.

## Commands and Tools

The two are easy to conflate, so it is worth being precise:

- A **command** is the action itself. It validates its input, mutates state or runs a query, and returns a success or failure result. It has no name or description of its own.
- A **tool** is a command wrapped with a name, description, and status text - the form an LLM can discover and call.

Studio's [Built-in Tools](https://www.ag-grid.com/studio/angular/ai-ax#tool-reference) are commands wrapped this way for the built-in runtime. The Toolkit hands you the command; you supply the wrapper your runtime expects.

## Retrieving a Command

Pass an `AgBuiltInAiCommandRef` to `api.defineAiCommand`:

```ts
const command = api.defineAiCommand({ type: 'AgExecuteQueryCommand' });

const schema = command.toJSONSchema();     // hand to your runtime as a tool definition
const result = await command.apply(args);  // { success: true, value } | { success: false, error }
```

Commands that carry configuration take a `params` field. `AgConfigureWidgetCommand` narrows its schema by widget type:

```ts
const configureBar = api.defineAiCommand({
    type: 'AgConfigureWidgetCommand',
    params: { widgetType: 'bar-chart-grouped' },
});
```

## Wrapping a Command as a Tool

You own the name, description, and status text - and any extra work around execution, such as validating input or trimming the result before it returns to the model.

```ts
import { tool } from 'your-ai-runtime';

const executeQueryCommand = api.defineAiCommand({ type: 'AgExecuteQueryCommand' });

const executeQueryTool = tool({
    name: 'execute_query',
    description: 'Query the full dataset available',
    schema: executeQueryCommand.toJSONSchema(),
    execute: async (params) => {
        const result = await executeQueryCommand.apply(params);

        if (!result.success) {
            return result;
        }

        // Trim to 50 rows to avoid overwhelming the context
        return result.value.slice(0, 50);
    },
});
```

Commands never throw - `apply()` returns a discriminated result, so handle the failure branch rather than wrapping calls in `try`/`catch`. To describe the data to the model or validate arguments first, pull the current schema and vocabulary from [Context](https://www.ag-grid.com/studio/angular/ai-context/).

## Built-In Commands

| Ref `type` | What it does |
| --- | --- |
| `AgExecuteQueryCommand` | Run a query against the data source. Supports aggregation (group-by with measures) and projection (raw row selection). |
| `AgAddPageFilterCommand` | Append a filter to the page-level filter list. |
| `AgRemovePageFilterCommand` | Remove a page-level filter, matching by its current state. |
| `AgAddWidgetFilterCommand` | Add a filter scoped to a single widget. |
| `AgRemoveWidgetFilterCommand` | Remove a widget-level filter, matching by its current state. |
| `AgAddWidgetCommand` | Add a widget to the canvas. |
| `AgPositionWidgetCommand` | Move or resize a widget. Omitted position fields preserve current values. |
| `AgRemoveWidgetCommand` | Permanently remove a widget from the page. |
| `AgConfigureWidgetCommand` | Configure a widget's data mapping, title, and formatting. Schema narrows by `params.widgetType`. |

Each button in the example sends a hardcoded prompt to OpenAI along with the matching command's JSON Schema as a single forced tool. The LLM returns tool arguments, which are handed straight to `command.apply()`. The console shows the message, schema, returned arguments, and command result for each.

#### Toolkit

```ts
import '@angular/compiler';
import { provideHttpClient } from '@angular/common/http';
import { bootstrapApplication } from '@angular/platform-browser';

import { AppComponent } from './app.component.ts';

const app = bootstrapApplication(AppComponent, {
    providers: [provideHttpClient()],
});
```

[Live example: Toolkit](https://www.ag-grid.com/studio/examples/ai-toolkit/ai-toolkit/angular/)

## JSON Schema Support

AG Studio generates [JSON Schema Draft 2020-12](https://json-schema.org/draft/2020-12). Some LLM providers and runtimes do not support every feature of this version, so you may need to adapt the schema:

- **Optional parameters** - some LLMs require every parameter in the `required` array. Model an optional field as a union with `null` (or a sentinel), then decode the result.
- **Nesting depth** - some LLMs limit schema nesting depth. Studio uses `$defs` and `$ref` to keep schemas shallow, but you may still need to break a schema up further.
- **Root schema** - some commands produce a union at the schema root, while some providers accept only an object there. Wrap the schema and unwrap the returned parameters before applying.

## Next Steps

- [Context](https://www.ag-grid.com/studio/angular/ai-context/) - Describe the data and dashboard to your model.
- [LLM Adapter](https://www.ag-grid.com/studio/angular/ai-adapter/) - The alternative: keep the built-in runtime and connect a provider.
