{
  "access": "public",
  "type": "reference",
  "format": "markdown",
  "title": "Prism Tools Reference",
  "chunked": true,
  "url": "https://library.datagrout.ai/prism-tools",
  "summary": "Transform, reshape, visualize, and export data passing through your workflows.",
  "content_markdown": "# Prism Tools\n\nTransform, reshape, visualize, and export data passing through your workflows.\n\nPrism tools operate on data in-flight. They transform structures via natural language, bridge incompatible types between systems, generate charts, render reports, convert formats, paginate large results, and analyze code. Prism generates verified code that executes in a sandboxed runtime -- repeated identical requests execute from cache at near-zero cost. All Prism tools are available at `data-grout@1/prism.*@1`.\n\n---\n\n## `prism.refract@1`\n\nReshape a data structure using a natural language instruction. Describe the transformation you want, pass the data, and Refract produces the result.\n\n### Parameters\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `goal` | string | yes | -- | Natural language description of the transformation (e.g. `\"flatten nested addresses into a single line\"`) |\n| `payload` | any | yes | -- | The data to transform |\n| `verbose` | boolean | no | false | Include transformation metadata in the response |\n| `chart` | string | no | -- | Also generate a chart from the result (e.g. `\"pie chart by category\"`) |\n\n### Example\n\n```json\n{\n  \"name\": \"data-grout@1/prism.refract@1\",\n  \"arguments\": {\n    \"goal\": \"group invoices by customer and sum totals\",\n    \"payload\": [\n      { \"customer\": \"Acme\", \"amount\": 500 },\n      { \"customer\": \"Globex\", \"amount\": 300 },\n      { \"customer\": \"Acme\", \"amount\": 200 }\n    ]\n  }\n}\n```\n\nResponse:\n\n```json\n{\n  \"result\": [\n    { \"customer\": \"Acme\", \"total\": 700, \"count\": 2 },\n    { \"customer\": \"Globex\", \"total\": 300, \"count\": 1 }\n  ]\n}\n```\n\n---\n\n## `prism.focus@1`\n\nBridge incompatible types between systems. Focus converts data from one semantic type to another, handling field mapping, renaming, and structural differences. The planner inserts Focus steps automatically when a workflow connects tools with mismatched types; you can also call it directly.\n\n### Parameters\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `data` | any | yes | -- | The data to convert |\n| `source_type` | string | yes | -- | Semantic type of the input (e.g. `crm.lead@1`) |\n| `target_type` | string | yes | -- | Semantic type to convert to (e.g. `billing.customer@1`) |\n| `source_annotations` | object | no | -- | Additional metadata about the source schema |\n| `target_annotations` | object | no | -- | Additional metadata about the target schema |\n| `context` | object | no | -- | Extra context to guide the conversion |\n\n### Example\n\n```json\n{\n  \"name\": \"data-grout@1/prism.focus@1\",\n  \"arguments\": {\n    \"data\": {\n      \"FirstName\": \"Jane\",\n      \"LastName\": \"Chen\",\n      \"Email\": \"jane@acme.com\",\n      \"Company\": \"Acme Corp\"\n    },\n    \"source_type\": \"crm.lead@1\",\n    \"target_type\": \"billing.customer@1\"\n  }\n}\n```\n\nResponse:\n\n```json\n{\n  \"result\": {\n    \"customer_name\": \"Jane Chen\",\n    \"email\": \"jane@acme.com\",\n    \"company_name\": \"Acme Corp\"\n  },\n  \"adapter_used\": \"crm.lead@1 -> billing.customer@1\",\n  \"confidence\": 0.96\n}\n```\n\nIf no direct adapter exists, Focus searches for a multi-hop path (e.g. `lead -> contact -> customer`) and applies each conversion in sequence.\n\n### Adapter Chain Pipeline\n\nFocus tries four strategies in priority order. Understanding this pipeline helps diagnose \"No bridge found\" errors:\n\n1. **Structural (annotation-driven)** — zero LLM tokens, fastest. Uses JMESPath selectors from `source_annotations` and the `io.in_sem` contract from `target_annotations` to map fields directly. Always pass annotations when available.\n\n2. **Prolog adapter chains** — zero LLM tokens. Searches the registered adapter graph for a path from source_type to target_type. Multi-hop chains (A → B → C) are supported.\n\n3. **SemioCatalog path** — zero LLM tokens. Looks up direct conversions, upcasts, and explicit adapters in the local type catalog (`semio_catalog.compact.json`).\n\n4. **Refract fallback** — uses LLM. Only attempted when `target_annotations` include an `io.in_sem` contract (so the LLM knows what fields to produce). Generates a CTC for the bridge.\n\n### Troubleshooting \"No bridge found\"\n\nIf Focus returns `\"success\": false` with `\"error\": \"No bridge found\"`, it means all four strategies failed. Common fixes:\n\n- **Pass annotations**: The most common fix. Include `source_annotations` and `target_annotations` with JMESPath selectors and `io.in_sem` contracts. This unlocks both structural mapping (strategy 1) and the refract fallback (strategy 4).\n\n- **Use prism.refract directly**: If you need a one-off conversion, `prism.refract` with a descriptive goal is simpler than setting up a permanent adapter. Focus will use refract as its final fallback automatically when `target_annotations` are provided.\n\n### Example with annotations\n\n```json\n{\n  \"name\": \"data-grout@1/prism.focus@1\",\n  \"arguments\": {\n    \"data\": { \"FirstName\": \"Jane\", \"Email\": \"jane@acme.com\" },\n    \"source_type\": \"crm.lead@1\",\n    \"target_type\": \"billing.customer@1\",\n    \"source_annotations\": {\n      \"selectors\": [\n        { \"field\": \"name\", \"path\": \"FirstName\", \"type\": \"core.name@1\" },\n        { \"field\": \"email\", \"path\": \"Email\", \"type\": \"core.email@1\" }\n      ]\n    },\n    \"target_annotations\": {\n      \"io\": {\n        \"in_sem\": [\n          { \"name\": \"customer_name\", \"type\": \"core.name@1\", \"mode\": \"required\" },\n          { \"name\": \"email\", \"type\": \"core.email@1\", \"mode\": \"required\" },\n          { \"name\": \"company\", \"type\": \"core.name@1\", \"mode\": \"maybe\" }\n        ]\n      }\n    }\n  }\n}\n```\n\n---\n\n## `prism.chart@1`\n\nGenerate a chart from data. Describe the visualization you want, pass the data, and Chart returns inline SVG content plus a hosted SVG URL. The chart is rendered by a Rust NIF and the SVG is uploaded to S3/CDN (or served from the app host as fallback).\n\n### Parameters\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `goal` | string | yes | -- | Natural language description of the chart (e.g. `\"bar chart of revenue by quarter\"`) |\n| `payload` | any | yes | -- | The data to visualize |\n| `formats` | array | no | `[\"svg\"]` | Output formats: `\"svg\"`, `\"sparkline\"`, `\"text\"`. Default returns `svg` + `svg_url` + `text_sparkline`. |\n| `format` | string | no | -- | **Deprecated** — use `formats` array instead. |\n| `chart_type` | string | no | auto-detected | Override chart type: `\"bar\"`, `\"line\"`, `\"scatter\"`, `\"hist\"` |\n| `title` | string | no | -- | Chart title |\n| `x_label` | string | no | -- | X-axis label |\n| `y_label` | string | no | -- | Y-axis label |\n| `width` | integer | no | 800 | Width in pixels |\n| `height` | integer | no | 500 | Height in pixels |\n\n### Default Response\n\nWith default formats `[\"svg\"]`, the response includes:\n\n- `svg` — Full SVG chart markup (render this directly or embed in HTML)\n- `svg_url` — Hosted URL to the SVG chart image\n- `image_url` — Legacy alias for `svg_url` (backwards compatible)\n- `text_sparkline` — Unicode block sparkline (`▁▂▄▆█`) — always included\n- `summary` — Statistics: min, max, mean, sum, count — always included\n- `chart_type` — Detected chart type\n- `spec_hash` — Content hash for caching\n\nSVG sparkline (`\"sparkline\"`) is opt-in — add it to the `formats` array to include it.\n\n### Example\n\n```json\n{\n  \"name\": \"data-grout@1/prism.chart@1\",\n  \"arguments\": {\n    \"goal\": \"bar chart of sales by region\",\n    \"payload\": [\n      { \"region\": \"North\", \"sales\": 42000 },\n      { \"region\": \"South\", \"sales\": 31000 },\n      { \"region\": \"East\", \"sales\": 58000 },\n      { \"region\": \"West\", \"sales\": 47000 }\n    ]\n  }\n}\n```\n\n---\n\n## `prism.analyze@1`\n\nStructured reasoning and analysis over data. Unlike `refract` (transforms data) or `render` (generates content), `analyze` performs **LLM-driven reasoning** and returns structured analytical findings with evidence and confidence levels.\n\n### Parameters\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `goal` | string | yes | -- | Analytical question or directive (e.g. `\"Who has latent leverage that Aldric doesn't know about?\"`) |\n| `payload` | any | no | -- | Data to analyze. Accepts JSON, a `cache_ref` string, or a stringified JSON payload |\n| `mode` | string | no | `\"exploratory\"` | Reasoning mode: `\"deductive\"` (multi-hop inference), `\"causal\"` (cause-effect), `\"comparative\"` (contrasts), `\"exploratory\"` (open-ended) |\n| `depth` | string | no | `\"shallow\"` | `\"shallow\"` for 3-5 key findings, `\"deep\"` for exhaustive analysis |\n| `output_format` | string | no | `\"structured\"` | `\"structured\"` (JSON findings), `\"narrative\"` (prose), `\"both\"` |\n\n### Modes\n\n- **Deductive** — Multi-hop inference chains. \"A implies B, B implies C, therefore A implies C.\" Each chain cites supporting data.\n- **Causal** — Cause-effect analysis. Traces cascading effects, identifies feedback loops and tipping points.\n- **Comparative** — Contrasts entities or scenarios. Ranks, highlights asymmetries, finds surprising differences.\n- **Exploratory** — Surfaces the most interesting patterns, anomalies, and non-obvious findings.\n\n### Example\n\n```json\n{\n  \"name\": \"data-grout@1/prism.analyze@1\",\n  \"arguments\": {\n    \"goal\": \"What cascading effects follow if Solvek's debt expires?\",\n    \"payload\": { \"...fact_graph...\" },\n    \"mode\": \"causal\",\n    \"depth\": \"deep\"\n  }\n}\n```\n\nResponse:\n\n```json\n{\n  \"findings\": [\n    {\n      \"finding\": \"Aldric seizes Solvek's assets, triggering Docks economic collapse\",\n      \"evidence\": [\"Solvek owes Aldric a debt expiring in one month\", \"Aldric has seizure rights\"],\n      \"confidence\": \"high\",\n      \"chain\": [\"debt expires\", \"Aldric exercises seizure rights\", \"Solvek loses assets\", \"Docks district collapses\"]\n    }\n  ],\n  \"mode\": \"causal\",\n  \"depth\": \"deep\",\n  \"goal\": \"What cascading effects follow if Solvek's debt expires?\"\n}\n```\n\n### As a `perform` parameter\n\n`analyze` is also available as a parameter on `discovery.perform`, creating a pipeline: **execute → analyze → refract → chart**. Pass an object with `goal`, optional `mode`, and optional `depth`:\n\n```json\n{\n  \"name\": \"data-grout@1/discovery.perform@1\",\n  \"arguments\": {\n    \"tool\": \"salesforce@v1/get-all-opportunities@v1\",\n    \"analyze\": {\n      \"goal\": \"Which deals are at risk and why?\",\n      \"mode\": \"deductive\"\n    }\n  }\n}\n```\n\n---\n\n## `prism.render@1`\n\nGenerate formatted reports or content from structured data. Render produces Markdown, HTML, or other content types based on a payload and optional formatting instructions.\n\n### Parameters\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `payload` | any | yes | -- | The data to render |\n| `format` | string | no | `\"markdown\"` | Output format: `\"markdown\"`, `\"html\"`, `\"text\"` |\n| `content_type` | string | no | -- | Type of content to generate: `\"report\"`, `\"summary\"`, `\"table\"`, `\"email\"` |\n| `goal` | string | no | -- | Natural language instructions for how to render |\n| `sections` | array | no | -- | Explicit section structure for the output |\n| `style` | object | no | -- | Style preferences (e.g. `{ \"tone\": \"formal\" }`) |\n| `metadata` | object | no | -- | Additional metadata to include in the output |\n\n### Example\n\n```json\n{\n  \"name\": \"data-grout@1/prism.render@1\",\n  \"arguments\": {\n    \"payload\": {\n      \"total_invoices\": 142,\n      \"total_revenue\": 284000,\n      \"overdue\": 12,\n      \"top_customer\": \"Acme Corp\"\n    },\n    \"content_type\": \"summary\",\n    \"goal\": \"executive summary of monthly billing\"\n  }\n}\n```\n\n---\n\n## `prism.export@1`\n\nConvert content between formats. Export takes rendered content (from Render or any other source) and converts it to a target format.\n\n### Parameters\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `content` | string | yes | -- | The content to convert |\n| `format` | string | yes | -- | Target format: `\"pdf\"`, `\"csv\"`, `\"json\"`, `\"html\"`, `\"markdown\"` |\n| `style` | object | no | -- | Style options for the output format |\n| `metadata` | object | no | -- | Metadata to embed in the output |\n| `options` | object | no | -- | Format-specific options (e.g. CSV delimiter, PDF page size) |\n\n### Example\n\n```json\n{\n  \"name\": \"data-grout@1/prism.export@1\",\n  \"arguments\": {\n    \"content\": \"| Customer | Revenue |\\n|---|---|\\n| Acme | $42,000 |\",\n    \"format\": \"csv\"\n  }\n}\n```\n\n---\n\n## `prism.paginate@1`\n\nNavigate large result sets page by page. Paginate caches the full result on first call and serves subsequent pages from cache.\n\n### Parameters\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `cache_ref` | string | no | -- | Reference from a previous paginate call to continue paging |\n| `payload` | any | no | -- | The full dataset (required on the first call; omit on subsequent pages) |\n| `page` | integer | no | 1 | Page number to retrieve |\n| `per_page` | integer | no | 25 | Items per page |\n| `advance` | boolean | no | false | Advance to the next page automatically |\n\n### Example\n\nFirst call:\n\n```json\n{\n  \"name\": \"data-grout@1/prism.paginate@1\",\n  \"arguments\": {\n    \"payload\": [ \"...large array...\" ],\n    \"per_page\": 10\n  }\n}\n```\n\nResponse includes a `cache_ref`. To get the next page:\n\n```json\n{\n  \"name\": \"data-grout@1/prism.paginate@1\",\n  \"arguments\": {\n    \"cache_ref\": \"pg_abc123\",\n    \"page\": 2\n  }\n}\n```\n\n---\n\n## Auto-Pagination for `-all-` Tools\n\nQuickBooks and Salesforce tools with `-all-` in their name (e.g., `get-all-invoices`, `get-all-accounts`) automatically paginate across multiple API pages. Two additional parameters are injected into their schemas:\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `limit` | integer | 10000 | Max records to fetch. Set to `0` or `-1` to fetch all (up to 50k) |\n| `refract` | string | -- | Optional goal for `prism.refract` to transform the fetched records |\n\n### How it works\n\n1. The tool executes normally, returning the first page of results\n2. If more data is available, remaining pages are fetched in parallel (QB) or sequentially (SF)\n3. QB continuation queries preserve the original WHERE/ORDER BY clauses from the tool's IR (no degradation to `SELECT * FROM entity`)\n4. All records are cached in `ResultCache` — the response includes `_cache_ref` for `prism.paginate`\n5. If `refract` is set, the full dataset is piped through `prism.refract` automatically\n\n### Input hardening\n\nUser-provided `refract` goals are sanitized via `InputSanitizer` before being interpolated into LLM prompts. Goals are wrapped in XML container tags (`<user_goal>...</user_goal>`) with explicit instructions to the model to treat the content as untrusted data. Field names from custom schemas are validated against a strict allowlist before being injected into queries.\n\n### Example: Fetch all invoices and summarize\n\n```json\n{\n  \"name\": \"quickbooks@v1/get-all-invoice-details-list@v1\",\n  \"arguments\": {\n    \"limit\": 5000,\n    \"refract\": \"total amount and count of invoices grouped by customer name\"\n  }\n}\n```\n\nThe response includes the refracted summary plus a `_cache_ref` for browsing the raw records via `prism.paginate`.\n\n### Schema-aware query optimization\n\nFor Salesforce users with custom fields (`__c`), the system automatically:\n\n1. Downloads the user's custom schema at OAuth auth time (via `SchemaSyncWorker`)\n2. Augments SOQL queries to include relevant custom fields\n3. When a `refract` goal is provided, attempts **query-level refraction** first -- generating a targeted SOQL query (with GROUP BY, aggregates, WHERE) that directly answers the goal without fetching all records\n4. Falls back to full pagination + in-memory refraction if query generation fails\n\n### Data teeing with `_cache_ref`\n\nThe `_cache_ref` returned by auto-paginated responses can be passed directly to any frame tool (`frame.slice`, `frame.filter`, `frame.sort`, `frame.group`, `frame.pivot`, `frame.join`) via the `cache_ref` parameter, avoiding re-transmission of large datasets.\n\n---\n\n> **Orient and Horizon have moved.** `prism.orient` and `prism.horizon` are now [`latent.orient`](latent-tools) and [`latent.horizon`](latent-tools) in the Latent tools suite. The old `prism.*` names are accepted as aliases for backward compatibility.\n\n---\n\n> **Code analysis tools have moved.** `code_lens`, `diff_analyzer`, and `code_query` are now part of the [Invariant tools](invariant-tools) suite.\n\n---\n\n## Caching\n\nPrism tools cache the generated transformation code. When you send an identical request (same goal, same structure), the cached version executes immediately at near-zero cost. This makes repeated transformations in loops or recurring workflows very efficient.\n"
}