Skip to Content
CLI Run and ExportAI inference

AI inference and per-node enrichment

The CLI can run an optional post-scan AI pipeline after structural detection. It proposes metadata patches for detected components and data flows, merges accepted proposals into the scan result, and records a summary in dataflow.json metadata.

The ai-per-node workstream focuses on third-party nodes: a bounded tool loop (tpAgent) reviews repository files, calls the configured model provider, and fills engineering/privacy/security fields. It can also emit a third-party data-flow insights block describing what categories of data appear to move to or from each vendor.

Structural scanning (Scan patterns) always runs first. AI inference is additive and can be disabled for reproducible Terraform-only output.

Mental model

End-to-end, a scan builds components and flows first, then optionally enriches them. Third-party data-flow insights are a separate metadata pass that runs only when AI ran and the data-flow flag is enabled.

Scan ├── Ingest + analyze + classify + data-flow detection │ └── Detect components (classifiers, topology rules, property patterns, …) ├── [if AI on] Enrich node properties (provider + heuristics, tpAgent tool loop) │ └── Merge accepted proposals into components / flows ├── Deterministic fallbacks (topology, third-party subType, cross-section flow trim, …) ├── Terraform minimal-service reduction (when applicable) ├── Stable component id assignment (cmp_1 … cmp_n) └── [if AI on + data-flow flag] metadata.aiInference.thirdPartyDataFlow (per third party) ├── Final third_party list (same ids as graph nodes) ├── Remap post-merge proposal/trace ids via stableComponentKey ├── Collect vendor-relevant files (detection evidence + agentic trace paths) ├── Pattern scan on those files (main “what data”) │ ├── Built-in pattern rules (financial, health, identifiers, …) │ ├── PII signals — cli/patterns/pii-signals.rules.yaml │ └── Non-PII signals — cli/patterns/non-pii-signals.rules.yaml ├── Merge integration_method / api_type → capabilities (rest, auth, storage, …) └── Fallback from AI proposal evidence text when pattern hits are thin

How to read this

  • Property enrichment changes what ends up on third-party (and other) nodes in graph — integration fields, vendor metadata, and similar node properties.
  • thirdPartyDataFlow does not add diagram edges; it adds read-only insights under metadata.aiInference (and, after import, data._cliDataFlowInsights on third-party nodes). It is built after fallbacks and stable cmp_* assignment so each entries[].componentId matches the final graph node id. Post-merge AI proposal and agentic-trace ids are bridged with stableComponentKey, not serviceName alone (avoids collisions such as Google vs Google AI in one section). Pattern YAML is the primary source for data categories; provider proposals mainly raise confidence and supply evidence when file patterns are sparse.
  • With AI off, you still get structural detection and deterministic topology/subType passes, but no thirdPartyDataFlow block.

Enable inference

AI inference is on by default (anonymous platform proxy, workspace platform AI, or BYOK). To run a structural-only scan, opt out with one of:

  • Flag: --no-ai-inference
  • Environment: SCAN_AI_INFERENCE=false
  • Config at scan root: "enableAiInference": false

You must also configure either:

  • BYOK provider + model + key (--byok-provider/--byok-model or --ai-provider/--ai-model, with SCAN_BYOK_PROVIDER, SCAN_BYOK_MODEL, SCAN_BYOK_API_KEY) — no workspace quota API, or
  • Platform AI with DATAPARADE_WORKSPACE_API_KEY — requires a successful quota preflight and draws from workspace scan quotas (scan slots + platform AI tokens), or
  • Anonymous platform AI (no workspace key) — IP-capped session; real token usage is stored on the job and debited when you claim the preview after signup.

A workspace API key with SCAN_AI_INFERENCE=false / --no-ai-inference does not run inference and does not use quota (structural heuristics only; upload still works).

Security defaults

  • .env / .env.* files are excluded from default ingest and never embedded in provider prompts (even if languages includes env). Scanning a single .env file path is also skipped.
  • dataparade config [path] prints aiApiKey as <redacted> when set (loads dataparade.config.json from the project at [path], same as scan).
  • Provider HTTP calls use a 120s default timeout (SCAN_AI_HTTP_TIMEOUT_MS).
  • --ai-endpoint / SCAN_AI_ENDPOINT can target any URL; only run inference on code you would share with that endpoint.
  • LangSmith tracing (when enabled) uploads summary-only metadata; failures do not fail the scan.
  • Proposal evidence must use exact repo-relative paths present in the scan (no fuzzy suffix matching).
  • Unknown SCAN_BYOK_PROVIDER / --ai-provider values log a warning and are ignored (the scan uses default provider settings).
  • Cloud presets (openai, anthropic, gemini, openrouter) without SCAN_BYOK_API_KEY skip network calls and emit a scan warning.
  • Only .env patterns are excluded by default; exclude other credential files with --exclude if needed.

Example:

SCAN_AI_INFERENCE=true \ SCAN_BYOK_PROVIDER=openai \ SCAN_BYOK_MODEL=gpt-4o-mini \ SCAN_BYOK_API_KEY=sk-... \ npx @dataparade/cli scan path/to/project --ai-inference

OpenRouter (same API key env var; use your OpenRouter  key):

SCAN_AI_INFERENCE=true \ SCAN_BYOK_PROVIDER=openrouter \ SCAN_BYOK_MODEL=openai/gpt-4o-mini \ SCAN_BYOK_API_KEY=sk-or-... \ npx @dataparade/cli scan path/to/project --ai-inference

See Environment variables and Scan arguments for the full flag and env surface.

Provider presets and API families

--ai-provider / aiProvider picks a preset (openai, anthropic, gemini, openrouter, local, mock). Presets are data, not one TypeScript file per vendor. Each preset points at an API family — the HTTP shape the CLI uses:

PresetAPI familyRole
openaiChat CompletionsOpenAI-style messages + JSON output
openrouterChat CompletionsOpenRouter gateway (OpenAI-compatible); model ids like openai/gpt-4o-mini
anthropicMessagesAnthropic system + messages
geminigenerateContentGemini with responseMimeType: application/json
localOllama generateLocal POST /api/generate
mockNo HTTP; empty proposals

Regardless of preset, model output is normalized through one pipeline into component/flow patches with evidence. Changing provider does not change merge rules or dataflow.json graph shape — only which HTTP API is called and which model name you pass (--ai-model / SCAN_BYOK_MODEL).

Default endpoints

When SCAN_AI_ENDPOINT / aiEndpoint is unset, each preset uses a built-in default:

PresetDefault endpoint
openaihttps://api.openai.com/v1/chat/completions
openrouterhttps://openrouter.ai/api/v1/chat/completions
anthropichttps://api.anthropic.com/v1/messages
geminihttps://generativelanguage.googleapis.com/v1beta/models/<model>:generateContent
localhttp://localhost:11434/api/generate (Ollama)

For Gemini, if you provide a base models URL in SCAN_AI_ENDPOINT (for example .../v1beta/models), the CLI appends /<model>:generateContent.

Example local override:

SCAN_AI_INFERENCE=true SCAN_BYOK_PROVIDER=local SCAN_BYOK_MODEL="llama3.1" SCAN_AI_ENDPOINT="http://YOUR_HOST:11434/api/generate"

Override the default URL for any preset with SCAN_AI_ENDPOINT / aiEndpoint (interpretation is family-specific).

Inference scope

aiInferenceScope (flag --ai-inference-scope, env SCAN_AI_INFERENCE_SCOPE) controls which candidates enter the AI queues:

ValueBehavior
defaultFull enrichment: third-party nodes and other supported candidate types.
third_party_onlyOnly third_party components are enriched; assets, actors, and flow-only work are skipped in the AI step. Useful to limit cost and latency when you only need vendor metadata.

Third-party tool loop (tpAgent)

For each third-party candidate, the orchestrator runs a bounded loop:

  1. Seed files from detection evidence and topology rules.
  2. Search the repo with deterministic keyword passes (capped).
  3. Provider infer — model proposes property patches with evidence references.
  4. Expand imports — follow import graph within file/review limits.
  5. Finalize when rounds exhaust or the agent completes.

Tune the loop with config file fields or environment variables (no dedicated CLI flags today):

SettingConfig keyEnvironment variableDefault
Max provider rounds per candidateaiToolLoopMaxRoundsSCAN_AI_TOOL_LOOP_MAX_ROUNDS3
Max distinct files in candidate contextaiToolLoopMaxFilesSCAN_AI_TOOL_LOOP_MAX_FILES48
Max seeded search terms per candidateaiToolLoopMaxSearchesSCAN_AI_TOOL_LOOP_MAX_SEARCHES12

Related cost controls (also apply to third-party batches):

  • aiMaxModelCalls / SCAN_AI_MAX_CALLS — cap total provider HTTP calls per queue.
  • aiBudgetTokens / SCAN_AI_BUDGET_TOKENS — Working token budget for the inference planner (default 12000). Platform/anonymous suggestedAiBudgetTokens is a server ceiling (anon default 100000, workspace up to remaining quota); the CLI takes the min of your working budget and that ceiling so a large cap cannot force a ~100k spend.
  • aiProviderConcurrency / SCAN_AI_PROVIDER_CONCURRENCY — max in-flight provider requests for tpAgent (wave batching).
  • aiMaxCandidatesPerAgent / SCAN_AI_MAX_CANDIDATES_PER_AGENT — per-agent queue cap (0 = unlimited).

Example config fragment:

{ "enableAiInference": true, "aiInferenceScope": "third_party_only", "aiProvider": "openai", "aiModel": "gpt-4o-mini", "aiMaxModelCalls": 12, "aiProviderConcurrency": 3, "aiToolLoopMaxRounds": 2, "aiToolLoopMaxFiles": 32, "aiToolLoopMaxSearches": 8 }

With --ai-verbose (or "aiVerbose": true in config), the CLI prints per-proposal apply/reject lines and token usage after the summary line.

Third-party data-flow insights

When AI inference runs and the data-flow flag is on, the CLI attaches metadata.aiInference.thirdPartyDataFlow: one entry per third-party component with direction, data categories, confidence band, capabilities, and file/line evidence (no raw source snippets in the written JSON). See Mental model for how pattern scan, capability merge, and evidence fallback fit together.

Per vendor, the builder:

  1. Gathers vendor-relevant files from structural evidence and tool-loop paths.
  2. Runs pattern scan (built-in rules plus PII / non-PII YAML) — primary source for dataShared categories.
  3. Adds capabilities from enriched integration_method / api_type on the component (e.g. rest, auth).
  4. If patterns found little, infers categories from applied AI proposal evidence reason text.

When a single file is used by two or more AI providers (e.g. one API route calling OpenAI and Google), prompt/document assembly signals on that file are attributed to each AI vendor in the file—not only the vendor whose name appears on the same line. Evidence for that path is tagged (shared_ai_handler); entries may include the note shared_ai_handler_prompt_attribution. Non-AI third parties in the same file are unchanged.

Enable or disable the metadata block (requires AI to be on; default is off until you opt in):

  • Config: "aiThirdPartyDataFlowEnabled": true
  • Environment: SCAN_AI_THIRD_PARTY_DATA_FLOW=true

When set to false, other AI enrichment still runs but thirdPartyDataFlow is omitted from metadata.

Entry shape (summary)

Each entries[] item includes:

  • componentId, componentName, optional service
  • direction: outbound_to_third_party, inbound_from_third_party, bidirectional, or unknown
  • dataShared[]: { category, labels[] } (categories such as credentials, identifiers, profile_data, telemetry, …)
  • confidence (0–1), confidenceBand (high | medium | low)
  • source: heuristic, provider, or provider_plus_heuristic
  • evidence[]: { filePath, startLine, endLine, reason }
  • optional notes[] (machine codes interpreted in the app UI, e.g. shared_ai_handler_prompt_attribution)

Totals: thirdPartiesAnalyzed, withDataShared.

The authoritative schema is aiInferenceSummarySchema in cli/src/core/schema/scan-result.schema.ts.

Agentic trace

When the tool loop runs, metadata.aiInference.agenticTrace lists per-candidate runs: candidate id, provider/model, round count, and toolCalls (tool name, arguments summary, outcome). The CLI import preview summary in the app shows run and tool-call counts when this block is present.

Console summary

With inference enabled, expect progress Running AI inference pipeline... and a line similar to:

[scan] ai-inference summary: candidates=… proposals=… applied=… rejected=… (provider/model)

Heuristic vs provider proposal counts and token totals are included in metadata; verbose mode adds per-proposal detail on stderr.

Debugging toggles

OpenAI response-shape and debug logging (optional):

  • SCAN_AI_DEBUG — verbose provider logging
  • DATAPARADE_AI_OPENAI_JSON_SCHEMA — OpenAI JSON schema mode
  • DATAPARADE_AI_OPENAI_JSON_SCHEMA_STRICT — strict JSON schema validation

Deterministic fallbacks (no AI)

Even without --ai-inference, the scan applies deterministic enrichment after the structural phases:

  • provider-topology.rules.yaml — managed service nodes and edges for cloud/SDK providers (Terraform resource types and SDK-backed vendors).
  • Third-party subtype heuristics — fill subType when the classifier left it empty.

PII / non-PII YAML is loaded during thirdPartyDataFlow construction (AI on + data-flow flag), not as a separate export path when AI is disabled.

For stable Terraform-only diagrams in CI, set SCAN_AI_INFERENCE=false so optional AI merge does not reshape components.

Privacy and output safety

  • AI uses snippets and paths from scanned files; raw sourceLocation.code is stripped from graph nodes and edges in dataflow.json (paths and line ranges remain).
  • Insights in metadata use the same evidence discipline (file + line range, no full file bodies in the export).

In the web app

After import, third-party nodes can carry _cliDataFlowInsights on node data (copied from metadata.aiInference.thirdPartyDataFlow during preview mapping). In Preview & Edit and on the diagram, open a third-party node and use the Data tab to review direction, categories, and evidence. See Creation and Imports for the import flow.

For the wrapper file layout and metadata fields, see Output and results.

Last updated on