# Example: analyze report data

Send report data to a task agent from code and get structured insights back — in complete or streaming mode, with caching to cut cost.

A common use for [task agents](/reference/task-agent-api/) is turning raw report data into
insight: summarize a sales export, flag anomalies in a usage report, or classify rows of
feedback. You configure the task agent once in **Agent Studio → Task Agents** (instructions,
input expectations, and an output schema), then call it from code with `runTask()`.

This page assumes a published task agent with the key `report_analyzer` whose output is
configured as **JSON**.

## Structured analysis (complete mode)

Pass your report rows and a question as `data`. Because the task agent returns `JSON`,
`runTask()` resolves with an object shaped by the output schema you defined in Studio.

```javascript
foldspace('when', 'ready', async () => {
  // Your report — rows pulled from your own API, warehouse, or export.
  const report = [
    { region: 'NA', revenue: 18200, refunds: 320, signups: 142 },
    { region: 'EU', revenue: 12750, refunds: 1180, signups: 98 },
    { region: 'APAC', revenue: 9400, refunds: 210, signups: 67 },
  ];

  try {
    const analysis = await foldspace
      .agent('YOUR-AGENT-API-NAME')
      .runTask({
        taskKey: 'report_analyzer',
        data: {
          report,
          question: 'Summarize the top revenue drivers and flag any anomalies.',
        },
      });

    // `analysis` matches your configured output schema, e.g.:
    // { summary: string, anomalies: Array<{ region, metric, note }>, topRegion: string }
    console.log(analysis.summary);
    renderAnomalies(analysis.anomalies);
  } catch (error) {
    console.error('Report analysis failed:', error);
  }
});
```

## Narrative summary (streaming mode)

For a long, written analysis you want to show as it's generated, configure the task agent's
response as **TEXT** and pass `streamOptions`. Each chunk arrives through `onMessage`, so you
can append to the UI progressively.

```javascript
foldspace.agent('YOUR-AGENT-API-NAME').runTask({
  taskKey: 'report_analyzer',
  data: { report, question: 'Write an executive summary of this quarter.' },
  streamOptions: {
    onStart: ({ abortStreamTask }) => {
      // Keep the handle so you can cancel a long run if the user navigates away.
      currentAbort = abortStreamTask;
    },
    onMessage: ({ textDelta, fullText }) => {
      appendToReport(textDelta); // or re-render with fullText
    },
    onComplete: ({ fullText }) => {
      finalizeReport(fullText);
    },
    onError: (error) => {
      showError(error);
    },
  },
});
```

:::note
Streaming is only supported for `TEXT` task agents. Keep a JSON output type when you need a
structured object back.
:::

## Cache repeated analyses

The same report analyzed twice should not pay for the model twice. Task agents cache results
automatically, so an identical `data` payload returns from cache. Tune it per call with
`cacheOptions`:

```javascript
foldspace.agent('YOUR-AGENT-API-NAME').runTask({
  taskKey: 'report_analyzer',
  data: { report, question: 'Summarize the top revenue drivers.' },
  cacheOptions: {
    // Re-use a cached analysis for an hour; dashboards that refresh often stay cheap.
    ttlSeconds: 3600,
    // Set bypass: true to force a fresh run when the underlying data changed.
    bypass: false,
  },
});
```

See the [Task Agent API reference](/reference/task-agent-api/#cache-options) for the full
caching behavior, and the [Task Agents guide](/user-guides/task-agents/) for configuring the
agent, its output schema, and reviewing model, latency, and cost in the logs.
