Skip to content

truto unified-mappings build authors the JSONata mapping rows that connect one integration's proxy API to a unified model (for example crm, ats, hris). It runs an agentic build, writes a local MappingFile JSON (for example acme.crm.mappings.json), and pushes nothing to Truto until you run truto unified-mappings apply.

# Build mappings for an integration against a unified model
truto unified-mappings build acme crm
 
# Audit the result without pushing
truto unified-mappings validate acme.crm.mappings.json
 
# Push when you are satisfied
truto unified-mappings apply acme.crm.mappings.json --target base

For each unified resource + method (for example contacts.list, accounts.get, deals.create) the build generates the JSONata that transforms the integration's raw proxy response into the unified schema shape — plus query_mapping, request_body_mapping, and error_mapping where the proxy method needs them.

This is the mapping-side companion to truto integrations build: build the integration first (so it has proxy resources), then build its unified mappings.

Prerequisites

Requirement Notes
Anthropic API key Required for all LLM work. Flag → $ANTHROPIC_API_KEYtruto profiles set-key anthropic → interactive prompt.
Truto login The build loads the integration config, the unified model schema, and any existing mapping rows from your environment.
An installed integration The integration must already exist with proxy resources (build it with truto integrations build).
Account or docs (required) Pass --account for live proxy samples, or at least one --source-url (URL or local file). Both may be combined. Without either, the build exits with an error.
Firecrawl API key Only when you pass a --source-url docs site that needs crawling (not raw OpenAPI / local files).
Local ONNX model Automatically downloaded on first use (~35 MB). Powers hybrid BM25 + cosine search over the --source-url index.

What happens during a build

The default flow (no flags) is agentic: Claude (Opus) orchestrates the build through tools, routing each unified resource/method to a proxy endpoint, sampling it, generating JSONata, validating, and committing the cell. A fixed per-cell pipeline still exists behind --structured for parity and cheaper runs — it still uses the LLM (Sonnet) to route and generate each mapping; only the orchestration is fixed, not the JSONata output.

1. Pre-flight

  • Resolve the Anthropic key (and Firecrawl when a --source-url is crawled).
  • Fetch the integration config (config.resources), the unified model schema (env override merged when --environment-id is set), and any existing mapping rows.
  • Inventory the proxy resources/methods and plan the cells — the unified resource × method pairs that a proxy endpoint can serve.
  • Load the mapping corpus (exemplars from other integrations) used for cribbing and leak detection.

2. Routing

The agent routes each unified resource/method to a proxy resource/method — including cross-name routes (unified accounts → proxy companies), multi-proxy-resource routes, and conditional (when-guarded) routes. Routing decisions are recorded so later steps and resumes stay consistent.

3. Ground the sample

Per cell, the build grounds generation on the richest sample it can find, in order:

  1. Live proxy (fetch_proxy_sample) when an --account is connected. Sampling is read-only — it only issues a GET for list/get and never runs create/update/delete against the connected account.
  2. DB documentation examples (read_doc_response_example).
  3. The --source-url index (one or more URLs/paths, merged) (search_source_docs), and as a last resort a single-page scrape (scrape_doc_page, needs Firecrawl).

Write cells (create / update / delete) are built from the proxy's documented request body even without a response example — the cell does its job through request_body_mapping.

4. Generate and validate

generateMappingField produces each field's JSONata; validate_mapping_output compiles it, evaluates it against the sample, and checks the result against the unified JSON Schema. A deterministic pass fixes proxy array paths, getlist aliases, and list wrappers, and rejects cross-integration leaks (verbatim copies of another integration's expressions).

5. Refinement loop (interactive)

In an interactive terminal the build ends in a refinement loop. Type a free-form instruction (for example engagements.create: strip the trailing Z from start times) and the agent re-builds the affected cell. Type :show to print the full per-cell review in the terminal. Press Enter on an empty line to finish. The loop is skipped with --no-refine, --yes, --only-missing, or when output is piped.

6. Output

The final MappingFile is written to --out or <integration>.<model>.mappings.json, with a build summary printed to the terminal and embedded in the file. The summary reports built / skipped / flagged counts and the next validate / apply commands.

Info

Resume: If the final MappingFile at --out (default <integration>.<model>.mappings.json) already exists, the build resumes from it — existing cells are kept and failed/empty cells are retried. It also carries forward mappings already applied on the platform (local cells win on conflict). Pass --fresh to ignore existing seeds and start from scratch.

Only missing cells: With --only-missing, only cells absent from the existing file are built — existing cells and skipped cells are untouched, failures are not retried.

MappingFile shape

The output is a MappingFile: integration + unified-model identifiers, a write_target, the generated cells[], and a build_summary.

Field Purpose
integration_name / unified_model_name What this file maps, by slug.
write_target base (team-owned rows) or env (per-environment override rows).
cells[] One entry per unified resource/method, each with a config (the mapping fields) and db_info (apply action).
build_summary status, counts (planned / built / skipped / flagged), built, skipped (with reasons), unbuilt_routed, and warnings.

Each cell's config carries the relevant mapping fields: response_mapping, and for read/write methods query_mapping, request_body_schema + request_body_mapping (required fields are marked), and error_mapping.

The build_summary is built for human review — it explains every gap. skipped cells list why no mapping was produced (for example "no proxy endpoint serves this method"), and warnings flag cells worth a second look (hardcoded custom_fields, create/update transform drift, single-key guards) grouped by cell and kind.

Useful flags

Flag Purpose
-a, --account <id> Integrated account ID for live proxy samples (read-only GET).
--source-url <url|path> API docs URL or local file path (repeatable, comma-separated; URLs and local OpenAPI/Postman/markdown files are merged into one source index). Supports glob patterns (e.g. './specs/*.json').
--yes Non-interactive mode: skip account/docs prompts. Requires --account and/or --source-url.
--anthropic-api-key <key> Override Anthropic API key (flag → $ANTHROPIC_API_KEY → profile → prompt).
--firecrawl-api-key <key> Override Firecrawl API key (flag → $FIRECRAWL_API_KEY → profile → prompt).
--no-firecrawl Skip Firecrawl; use cheaper extraction only for doc sites.
--resources <list> Comma-separated unified resources to build (default: all planned).
--methods <list> Comma-separated methods (list,get,create,update,delete,…).
--structured Run a fixed per-cell pipeline instead of the agentic loop (still LLM-generated; only the orchestration is fixed).
--no-web-search Disable the web_search / web_fetch tools and the source-sample web-search rung (no outbound web calls).
--fresh Ignore an existing working/final MappingFile and start from scratch.
--only-missing Build only cells absent from the existing file; do not retry failures or modify existing cells.
--no-refine Skip the interactive post-build refinement loop.
--fail-fast Stop on the first cell error (default: skip failed cells and continue).
--environment-id <id> Resolve schema overrides and target env override rows.
--target <base|env> Write-target hint recorded in the file for apply (default base).
--out <file> Output path (default <integration>.<model>.mappings.json).
--unified-mapping-dir <path> Corpus of unified mapping exemplars ($TRUTO_UNIFIED_MAPPING_DIR or profile unifiedMappingDir).
--integration-config-dir <path> Local proxy-config corpus for exemplars.
--debug-log <path> / --no-debug-log JSONL transcript of the build (default on, under ~/.truto/logs/).
--anthropic-model <model> Override the model for all LLM tiers.
--agent Deprecated no-op — the agentic loop is already the default.

Run truto unified-mappings build --help for the complete list.

Bring-your-own keys

Key Required when
ANTHROPIC_API_KEY Always
FIRECRAWL_API_KEY A --source-url docs site needs crawling

Resolution order for each: CLI flag → environment variable → truto profiles set-key → interactive prompt on a TTY.

Note: Hybrid search (BM25 + cosine) is now powered by a local ONNX model downloaded automatically on first use. No external API key is required.

Web tools

By default the agent can call the Anthropic-side web_search / web_fetch server tools to ground a low-confidence route or an undocumented field against the provider's official docs (capped by max_uses). Pass --no-web-search to disable both those tools and the source-index web-search rung — useful for builds where you want no outbound web calls beyond the proxy and Truto APIs.

Validate

Audit a MappingFile without applying — deterministic, no LLM, no writes:

truto unified-mappings validate acme.crm.mappings.json
truto unified-mappings validate acme.crm.mappings.json -v   # list advisory warnings

Validation re-checks every cell's JSONata and schema conformance and exits non-zero on errors. Advisory warnings (the per-cell review flags from build_summary.warnings) never fail validation; they are summarized by default and listed in full with -v. Pass --environment-id to resolve env schema overrides.

Apply

Push the reviewed MappingFile to the platform:

# Preview the payloads without writing
truto unified-mappings apply acme.crm.mappings.json --dry-run
 
# Apply to base rows (or env override rows)
truto unified-mappings apply acme.crm.mappings.json --target base
truto unified-mappings apply acme.crm.mappings.json --target env

Apply upserts each cell as a unified_model_resource_method row (or the environment_unified_model_resource_method override when --target env), using the db_info action recorded per cell (create / update / skip).

Flag Effect
--target <base|env> Write base rows or per-environment overrides
--dry-run Validate and print payloads; no API calls
--yes Skip confirmation prompts

Examples

# Live-grounded build for a connected account, then validate + apply
export ANTHROPIC_API_KEY=sk-ant-...
ACCOUNT=<integrated-account-id>
truto unified-mappings build acme crm --account $ACCOUNT
truto unified-mappings validate acme.crm.mappings.json
truto unified-mappings apply acme.crm.mappings.json --target base
 
# Doc-grounded build with a source URL (no account)
truto unified-mappings build acme crm \
  --source-url https://docs.acme.com/openapi.json --yes
 
# Multiple sources: remote URL + local files + glob
truto unified-mappings build acme crm \
  --source-url https://docs.acme.com/api \
  --source-url ./specs/acme-openapi.json \
  --source-url './notes/*.md' --yes
 
# Only build the cells you are missing, just for two resources
truto unified-mappings build acme crm --resources contacts,accounts --only-missing
 
# Fixed pipeline, no web calls
truto unified-mappings build acme crm --structured --no-web-search

Next steps