Skip to main content
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.
async generateGraph(
  params: GenerateGraphParams,
  onProgress?: (event: ProgressEvent) => void,
  signal?: AbortSignal
): Promise<GenerateGraphResponse>

generateGraphStream

Returns an async iterator that yields events as they arrive.
async generateGraphStream(
  params: GenerateGraphParams,
  signal?: AbortSignal
): Promise<AsyncIterableIterator<SSEEvent<GenerateGraphResponse>>>

Parameters

interface GenerateGraphParams {
  config: GraphConfig;
  userPrompt?: string;
  metadata?: Metadata;
  storytellingOptions?: StorytellingOptions;
}
FieldTypeRequiredDescription
configGraphConfigYesThe current chart configuration
userPromptstringNoNatural language instruction
metadataMetadataNoRequest tracking information
storytellingOptionsStorytellingOptionsNoPrune storytelling from config content client-side (SDK only).

Metadata

interface Metadata {
  callId?: string;
  locale?: string;
  effort?: 'low' | 'medium' | 'high';
  /** @deprecated Prefer `effort`. */
  storytellingEffort?: 'none' | 'low' | 'medium' | 'high';
}
FieldTypeDescription
callIdstringOptional. Identifier for tracking and debugging.
localestringLocale 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.
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

interface GenerateGraphResponse {
  config: GraphConfig;
  response: {
    message: string;
    steps?: string[];
  };
}
FieldTypeDescription
configGraphConfigUpdated chart configuration. Narrative (title, subtitle, caption) is embedded in config.content as TipTap JSON documents; see Invocation effort and chart narrative.
response.messagestringExplanation of changes made
response.stepsstring[]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).
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

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:
const result = await ai.generateGraph(
  {
    config,
    userPrompt: 'Add a trend line and change colors to blue',
  },
  (progress) => {
    console.log(progress.message);
  }
);

ProgressEvent

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

With Abort Signal

Cancel a request mid-operation:
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:
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 for cancellation and React patterns.

Error Handling

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 for retry behavior and error types.