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

# Chart Maker Agent

Modify charts using natural language. Send a `GraphConfig` and a prompt, receive an updated `GraphConfig`.

## Methods

### generateGraph

Processes the request and returns the final result. Internally handles streaming and collects the response.

```typescript theme={null}
async generateGraph(
  params: GenerateGraphParams,
  onProgress?: (event: ProgressEvent) => void,
  signal?: AbortSignal
): Promise<GenerateGraphResponse>
```

### generateGraphStream

Returns an async iterator that yields events as they arrive.

```typescript theme={null}
async generateGraphStream(
  params: GenerateGraphParams,
  signal?: AbortSignal
): Promise<AsyncIterableIterator<SSEEvent<GenerateGraphResponse>>>
```

## Parameters

```typescript theme={null}
interface GenerateGraphParams {
  config: GraphConfig;
  userPrompt?: string;
  metadata?: Metadata;
  storytellingOptions?: StorytellingOptions;
}
```

| Field                 | Type                  | Required | Description                                                    |
| --------------------- | --------------------- | -------- | -------------------------------------------------------------- |
| `config`              | `GraphConfig`         | Yes      | The current chart configuration                                |
| `userPrompt`          | `string`              | No       | Natural language instruction                                   |
| `metadata`            | `Metadata`            | No       | Request tracking information                                   |
| `storytellingOptions` | `StorytellingOptions` | No       | Prune storytelling from config content client-side (SDK only). |

### Metadata

```typescript theme={null}
interface Metadata {
  callId?: string;
  locale?: string;
  effort?: 'low' | 'medium' | 'high';
  /** @deprecated Prefer `effort`. */
  storytellingEffort?: 'none' | 'low' | 'medium' | 'high';
}
```

| Field                | Type                                    | Description                                                                                                                                                                                                                                                 |
| -------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `callId`             | `string`                                | Optional. Identifier for tracking and debugging.                                                                                                                                                                                                            |
| `locale`             | `string`                                | Locale for responses (e.g., `en-US`, `fr-FR`).                                                                                                                                                                                                              |
| `effort`             | `'low' \| 'medium' \| 'high'`           | Preferred invocation tier; stored on the invocation and forwarded to nested agents. Default is **`medium`** when omitted (and nothing deprecated is used to infer it). See [Invocation effort and chart narrative](#invocation-effort-and-chart-narrative). |
| `storytellingEffort` | `'none' \| 'low' \| 'medium' \| 'high'` | **Deprecated** — prefer `effort`. Still accepted; when only this field is set, the server infers `effort` for the rest of the pipeline.                                                                                                                     |

## Response

```typescript theme={null}
interface GenerateGraphResponse {
  config: GraphConfig;
  response: {
    message: string;
    steps?: string[];
  };
}
```

| Field              | Type          | Description                                                                                                                                                                                                      |
| ------------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `config`           | `GraphConfig` | Updated chart configuration. Narrative (title, subtitle, caption) is embedded in `config.content` as TipTap JSON documents; see [Invocation effort and chart narrative](#invocation-effort-and-chart-narrative). |
| `response.message` | `string`      | Explanation of changes made                                                                                                                                                                                      |
| `response.steps`   | `string[]`    | Breakdown of individual modifications                                                                                                                                                                            |

The response is validated with Zod. Invalid responses throw an error.

***

## Invocation effort and chart narrative

`metadata.effort` selects how heavy the invocation is: it is stored on the request, forwarded into agent invocations (including tools that run nested agents), and drives defaults when you do not send `storytellingEffort`.

For **chart generation**, the chart agent still consumes a storytelling level (`none` / `low` / `medium` / `high`). The server sets that level as follows:

* If you send **only** `effort`, the chart storytelling level is derived from `effort` (default `effort` is **`medium`**, which matches the narrative band you previously got from omitting metadata or using the old default).
* If you send **only** `storytellingEffort` (deprecated), the chart uses that value directly and the server infers `effort` for the rest of the stack.
* If you send **both**, `storytellingEffort` wins for the chart so existing explicit chart settings keep working; `effort` still applies everywhere else.

There is no **`none`** value on `effort`; to drop narrative fields in the client, use **`storytellingOptions`** on `GenerateGraphParams` (see [StorytellingOptions](/agents/reference/types#storytellingoptions)).

```typescript theme={null}
const result = await ai.generateGraph({
  config,
  userPrompt: 'Show sales by region and add a clear title',
  metadata: { effort: 'high' },
});

// Narrative is embedded in the config content as TipTap JSON
console.log(result.config.content?.title); // TipTap JSON doc with title text
console.log(result.config.content?.subtitle);
console.log(result.config.content?.caption);
```

***

## Basic Usage

```typescript theme={null}
import { GraphyAiSdk } from '@graphysdk/agents-sdk';
import type { GraphConfig } from '@graphysdk/core';

const ai = new GraphyAiSdk({
  apiKey: process.env.GRAPHY_API_KEY,
  baseUrl: 'https://agents.graphy.dev',
});

const config: GraphConfig = {
  type: 'column',
  data: {
    columns: [
      { key: 'month', label: 'Month' },
      { key: 'sales', label: 'Sales' },
    ],
    rows: [
      { month: 'Jan', sales: 100 },
      { month: 'Feb', sales: 120 },
      { month: 'Mar', sales: 115 },
    ],
  },
};

const result = await ai.generateGraph({
  config,
  userPrompt: 'Change this to a bar chart and sort by sales descending',
});

console.log(result.config); // Updated GraphConfig
console.log(result.response.message); // Explanation
```

***

## With Progress Callback

Use the `onProgress` callback to show real-time progress without full streaming:

```typescript theme={null}
const result = await ai.generateGraph(
  {
    config,
    userPrompt: 'Add a trend line and change colors to blue',
  },
  (progress) => {
    console.log(progress.message);
  }
);
```

### ProgressEvent

```typescript theme={null}
interface ProgressEvent {
  type: 'progress';
  message: string;
  agentId?: string;
  executionId?: string;
  iteration?: number;
  metadata?: Record<string, unknown>;
}
```

***

## With Abort Signal

Cancel a request mid-operation:

```typescript theme={null}
const controller = new AbortController();

// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);

try {
  const result = await ai.generateGraph(
    { config, userPrompt: 'Create a complex visualization' },
    undefined,
    controller.signal
  );
} catch (error) {
  if (error instanceof Error && error.name === 'AbortError') {
    console.log('Request cancelled');
  }
}
```

***

## Streaming

For full control over the event stream:

```typescript theme={null}
import { isProgressEvent, isCompleteEvent, isErrorEvent } from '@graphysdk/agents-sdk';

const stream = await ai.generateGraphStream({
  config,
  userPrompt: 'Add annotations for peak values',
});

for await (const event of stream) {
  if (isProgressEvent(event)) {
    console.log(event.message);
  }

  if (isCompleteEvent(event)) {
    console.log('Result:', event.data.config);
  }

  if (isErrorEvent(event)) {
    console.error('Error:', event.error);
  }
}
```

See [Streaming](/agents/sdk/streaming) for cancellation and React patterns.

***

## Error Handling

```typescript theme={null}
import { isGraphyApiError } from '@graphysdk/agents-sdk';

try {
  const result = await ai.generateGraph({
    config,
    userPrompt: 'Change to a bar chart',
  });
} catch (error) {
  if (isGraphyApiError(error)) {
    console.error('API error:', error.message);
  } else if (error instanceof Error && error.name === 'AbortError') {
    console.log('Request cancelled');
  } else {
    console.error('Unexpected error:', error);
  }
}
```

See [Error Handling](/agents/sdk/errors) for retry behavior and error types.
