Prism Tools
Transform, reshape, visualize, and export data passing through your workflows.
Prism 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.
prism.refract@1
Reshape a data structure using a natural language instruction. Describe the transformation you want, pass the data, and Refract produces the result.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
goal |
string | yes | β |
Natural language description of the transformation (e.g. "flatten nested addresses into a single line") |
payload |
any | yes | β | The data to transform |
verbose |
boolean | no | false | Include transformation metadata in the response |
chart |
string | no | β |
Also generate a chart from the result (e.g. "pie chart by category") |
Example
{
"name": "data-grout@1/prism.refract@1",
"arguments": {
"goal": "group invoices by customer and sum totals",
"payload": [
{ "customer": "Acme", "amount": 500 },
{ "customer": "Globex", "amount": 300 },
{ "customer": "Acme", "amount": 200 }
]
}
}
Response:
{
"result": [
{ "customer": "Acme", "total": 700, "count": 2 },
{ "customer": "Globex", "total": 300, "count": 1 }
]
}
prism.focus@1
Bridge 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.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
data |
any | yes | β | The data to convert |
source_type |
string | yes | β |
Semantic type of the input (e.g. crm.lead@1) |
target_type |
string | yes | β |
Semantic type to convert to (e.g. billing.customer@1) |
source_annotations |
object | no | β | Additional metadata about the source schema |
target_annotations |
object | no | β | Additional metadata about the target schema |
context |
object | no | β | Extra context to guide the conversion |
Example
{
"name": "data-grout@1/prism.focus@1",
"arguments": {
"data": {
"FirstName": "Jane",
"LastName": "Chen",
"Email": "jane@acme.com",
"Company": "Acme Corp"
},
"source_type": "crm.lead@1",
"target_type": "billing.customer@1"
}
}
Response:
{
"result": {
"customer_name": "Jane Chen",
"email": "jane@acme.com",
"company_name": "Acme Corp"
},
"adapter_used": "crm.lead@1 -> billing.customer@1",
"confidence": 0.96
}
If no direct adapter exists, Focus searches for a multi-hop path (e.g. lead -> contact -> customer) and applies each conversion in sequence.
Adapter Chain Pipeline
Focus tries four strategies in priority order. Understanding this pipeline helps diagnose βNo bridge foundβ errors:
-
Structural (annotation-driven) β zero LLM tokens, fastest. Uses JMESPath selectors from
source_annotationsand theio.in_semcontract fromtarget_annotationsto map fields directly. Always pass annotations when available. -
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.
-
SemioCatalog path β zero LLM tokens. Looks up direct conversions, upcasts, and explicit adapters in the local type catalog (
semio_catalog.compact.json). -
Refract fallback β uses LLM. Only attempted when
target_annotationsinclude anio.in_semcontract (so the LLM knows what fields to produce). Generates a CTC for the bridge.
Troubleshooting βNo bridge foundβ
If Focus returns "success": false with "error": "No bridge found", it means all four strategies failed. Common fixes:
-
Pass annotations: The most common fix. Include
source_annotationsandtarget_annotationswith JMESPath selectors andio.in_semcontracts. This unlocks both structural mapping (strategy 1) and the refract fallback (strategy 4). -
Use prism.refract directly: If you need a one-off conversion,
prism.refractwith a descriptive goal is simpler than setting up a permanent adapter. Focus will use refract as its final fallback automatically whentarget_annotationsare provided.
Example with annotations
{
"name": "data-grout@1/prism.focus@1",
"arguments": {
"data": { "FirstName": "Jane", "Email": "jane@acme.com" },
"source_type": "crm.lead@1",
"target_type": "billing.customer@1",
"source_annotations": {
"selectors": [
{ "field": "name", "path": "FirstName", "type": "core.name@1" },
{ "field": "email", "path": "Email", "type": "core.email@1" }
]
},
"target_annotations": {
"io": {
"in_sem": [
{ "name": "customer_name", "type": "core.name@1", "mode": "required" },
{ "name": "email", "type": "core.email@1", "mode": "required" },
{ "name": "company", "type": "core.name@1", "mode": "maybe" }
]
}
}
}
}
prism.chart@1
Generate 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).
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
goal |
string | yes | β |
Natural language description of the chart (e.g. "bar chart of revenue by quarter") |
payload |
any | yes | β | The data to visualize |
formats |
array | no |
["svg"] |
Output formats: "svg", "sparkline", "text". Default returns svg + svg_url + text_sparkline. |
format |
string | no | β |
Deprecated β use formats array instead. |
chart_type |
string | no | auto-detected |
Override chart type: "bar", "line", "scatter", "hist" |
title |
string | no | β | Chart title |
x_label |
string | no | β | X-axis label |
y_label |
string | no | β | Y-axis label |
width |
integer | no | 800 | Width in pixels |
height |
integer | no | 500 | Height in pixels |
Default Response
With default formats ["svg"], the response includes:
-
svgβ Full SVG chart markup (render this directly or embed in HTML) -
svg_urlβ Hosted URL to the SVG chart image -
image_urlβ Legacy alias forsvg_url(backwards compatible) -
text_sparklineβ Unicode block sparkline (βββββ) β always included -
summaryβ Statistics: min, max, mean, sum, count β always included -
chart_typeβ Detected chart type -
spec_hashβ Content hash for caching
SVG sparkline ("sparkline") is opt-in β add it to the formats array to include it.
Example
{
"name": "data-grout@1/prism.chart@1",
"arguments": {
"goal": "bar chart of sales by region",
"payload": [
{ "region": "North", "sales": 42000 },
{ "region": "South", "sales": 31000 },
{ "region": "East", "sales": 58000 },
{ "region": "West", "sales": 47000 }
]
}
}
prism.analyze@1
Structured 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.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
goal |
string | yes | β |
Analytical question or directive (e.g. "Who has latent leverage that Aldric doesn't know about?") |
payload |
any | no | β |
Data to analyze. Accepts JSON, a cache_ref string, or a stringified JSON payload |
mode |
string | no |
"exploratory" |
Reasoning mode: "deductive" (multi-hop inference), "causal" (cause-effect), "comparative" (contrasts), "exploratory" (open-ended) |
depth |
string | no |
"shallow" |
"shallow" for 3-5 key findings, "deep" for exhaustive analysis |
output_format |
string | no |
"structured" |
"structured" (JSON findings), "narrative" (prose), "both" |
Modes
- Deductive β Multi-hop inference chains. βA implies B, B implies C, therefore A implies C.β Each chain cites supporting data.
- Causal β Cause-effect analysis. Traces cascading effects, identifies feedback loops and tipping points.
- Comparative β Contrasts entities or scenarios. Ranks, highlights asymmetries, finds surprising differences.
- Exploratory β Surfaces the most interesting patterns, anomalies, and non-obvious findings.
Example
{
"name": "data-grout@1/prism.analyze@1",
"arguments": {
"goal": "What cascading effects follow if Solvek's debt expires?",
"payload": { "...fact_graph..." },
"mode": "causal",
"depth": "deep"
}
}
Response:
{
"findings": [
{
"finding": "Aldric seizes Solvek's assets, triggering Docks economic collapse",
"evidence": ["Solvek owes Aldric a debt expiring in one month", "Aldric has seizure rights"],
"confidence": "high",
"chain": ["debt expires", "Aldric exercises seizure rights", "Solvek loses assets", "Docks district collapses"]
}
],
"mode": "causal",
"depth": "deep",
"goal": "What cascading effects follow if Solvek's debt expires?"
}
As a perform parameter
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:
{
"name": "data-grout@1/discovery.perform@1",
"arguments": {
"tool": "salesforce@v1/get-all-opportunities@v1",
"analyze": {
"goal": "Which deals are at risk and why?",
"mode": "deductive"
}
}
}
prism.render@1
Generate formatted reports or content from structured data. Render produces Markdown, HTML, or other content types based on a payload and optional formatting instructions.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
payload |
any | yes | β | The data to render |
format |
string | no |
"markdown" |
Output format: "markdown", "html", "text" |
content_type |
string | no | β |
Type of content to generate: "report", "summary", "table", "email" |
goal |
string | no | β | Natural language instructions for how to render |
sections |
array | no | β | Explicit section structure for the output |
style |
object | no | β |
Style preferences (e.g. { "tone": "formal" }) |
metadata |
object | no | β | Additional metadata to include in the output |
Example
{
"name": "data-grout@1/prism.render@1",
"arguments": {
"payload": {
"total_invoices": 142,
"total_revenue": 284000,
"overdue": 12,
"top_customer": "Acme Corp"
},
"content_type": "summary",
"goal": "executive summary of monthly billing"
}
}
prism.export@1
Convert content between formats. Export takes rendered content (from Render or any other source) and converts it to a target format.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
content |
string | yes | β | The content to convert |
format |
string | yes | β |
Target format: "pdf", "csv", "json", "html", "markdown" |
style |
object | no | β | Style options for the output format |
metadata |
object | no | β | Metadata to embed in the output |
options |
object | no | β | Format-specific options (e.g. CSV delimiter, PDF page size) |
Example
{
"name": "data-grout@1/prism.export@1",
"arguments": {
"content": "| Customer | Revenue |\n|---|---|\n| Acme | $42,000 |",
"format": "csv"
}
}
prism.paginate@1
Navigate large result sets page by page. Paginate caches the full result on first call and serves subsequent pages from cache.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
cache_ref |
string | no | β | Reference from a previous paginate call to continue paging |
payload |
any | no | β | The full dataset (required on the first call; omit on subsequent pages) |
page |
integer | no | 1 | Page number to retrieve |
per_page |
integer | no | 25 | Items per page |
advance |
boolean | no | false | Advance to the next page automatically |
Example
First call:
{
"name": "data-grout@1/prism.paginate@1",
"arguments": {
"payload": [ "...large array..." ],
"per_page": 10
}
}
Response includes a cache_ref. To get the next page:
{
"name": "data-grout@1/prism.paginate@1",
"arguments": {
"cache_ref": "pg_abc123",
"page": 2
}
}
Auto-Pagination for -all- Tools
QuickBooks 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:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 10000 |
Max records to fetch. Set to 0 or -1 to fetch all (up to 50k) |
refract |
string | β |
Optional goal for prism.refract to transform the fetched records |
How it works
- The tool executes normally, returning the first page of results
- If more data is available, remaining pages are fetched in parallel (QB) or sequentially (SF)
-
QB continuation queries preserve the original WHERE/ORDER BY clauses from the toolβs IR (no degradation to
SELECT * FROM entity) -
All records are cached in
ResultCacheβ the response includes_cache_refforprism.paginate -
If
refractis set, the full dataset is piped throughprism.refractautomatically
Input hardening
User-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.
Example: Fetch all invoices and summarize
{
"name": "quickbooks@v1/get-all-invoice-details-list@v1",
"arguments": {
"limit": 5000,
"refract": "total amount and count of invoices grouped by customer name"
}
}
The response includes the refracted summary plus a _cache_ref for browsing the raw records via prism.paginate.
Schema-aware query optimization
For Salesforce users with custom fields (__c), the system automatically:
-
Downloads the userβs custom schema at OAuth auth time (via
SchemaSyncWorker) - Augments SOQL queries to include relevant custom fields
-
When a
refractgoal 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 - Falls back to full pagination + in-memory refraction if query generation fails
Data teeing with _cache_ref
The _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.
Orient and Horizon have moved.
prism.orientandprism.horizonare nowlatent.orientandlatent.horizonin the Latent tools suite. The oldprism.*names are accepted as aliases for backward compatibility.
Code analysis tools have moved.
code_lens,diff_analyzer, andcode_queryare now part of the Invariant tools suite.
Caching
Prism 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.