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).
Integrated account (recommended) Pass --account to ground mappings on live proxy samples. Without one, the build falls back to documentation samples.
Firecrawl API key Only when you pass a --source-url docs site that needs crawling (not raw OpenAPI / local files).
OpenAI API key Optional. Embeds the --source-url index for hybrid search; omit with --no-embeddings for BM25-only.

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 / OpenAI 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 (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. 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 a working file (<integration>.<model>.mappings.working.json) already exists with built cells, the build resumes from it instead of starting over. Pass --fresh to ignore it.

Only missing cells: On an existing file, --only-missing builds only the cells not yet present — it does not retry failures or modify cells already on disk.

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> API documentation URL for response examples (sample ladder: live → DB → source).
--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
OPENAI_API_KEY Optional embeddings for the --source-url index (unless --no-embeddings)

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

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
 
# 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