Unified mappings build
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 baseFor 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_KEY → truto 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-urlis crawled). - Fetch the integration config (
config.resources), the unified model schema (env override merged when--environment-idis 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:
- Live proxy (
fetch_proxy_sample) when an--accountis connected. Sampling is read-only — it only issues aGETforlist/getand never runs create/update/delete against the connected account. - DB documentation examples (
read_doc_response_example). - The
--source-urlindex (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, get→list 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.
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 warningsValidation 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 envApply 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-searchNext steps
- Managing integrations — build the integration first so it has proxy resources
- AI-powered integration build — the integration-side companion flow
- What are Unified APIs? — the models you are mapping to
- JSONata Binding Reference — the expression language used in every mapping field
- Data plane —
unified test-mappingto iterate on a singleresponse_mappinglocally