Repository navigation
feat(genkit): @traceai/genkit span processor (TH-8240) - #216
Merged
Merged
Conversation
The Node OTLP exporter streams with Transfer-Encoding: chunked and sends no Content-Length. The Receiver read Content-Length only, so every Node export came back 400 with zero spans; two TH-8103 children had to put a de-chunking relay in front of it. Receiver now accepts both framings. It also records one entry per accepted export (path, lower-cased headers, flattened resource attributes) via requests(), so a contract test can assert X-Api-Key/X-Secret-Key and project_name through the shared harness instead of a private recorder. Verified: 6 harness tests pass, and the TanStack example's real Node exporter delivered 4 chunked exports (4 spans, collector path, both auth headers, project_name/project_type) with no relay. Refs: TH-8339, TH-8103
New TypeScript package typescript/packages/traceai_genkit (@traceai/genkit,
JS only). FIGenkitSpanProcessor is passed to Genkit's
enableTelemetry({ spanProcessors }). Genkit's own telemetry-server processor
stays first (@genkit-ai/core src/tracing/node-telemetry-provider.ts:66-77), so
the Dev UI keeps working. For each ended Genkit span the processor builds a
mapped copy (Genkit's span is never modified) and hands it to the
@traceai/fi-core provider's span processor and OTLP exporter with the Future
AGI resource. Also: flushOnSignals(flush) for SIGTERM/SIGINT, README, root
README row, jest unit tests, shared-harness contract test, lockfile entries.
Tested: genkit 1.42.0 (@genkit-ai/core 1.42.0, @genkit-ai/ai 1.42.0, all
Apache-2.0 per node_modules LICENSE/package.json), Node 20.20.2, 22.23.3,
26.8.1. genkit is a peerDependency (^1.42.0) and a 1.42.0 devDependency only.
Inventory (contract/inventory.mjs, Genkit's mockModel from genkit/testing,
one flow with an ai.run() step and generateStream with a tool loop, called
and streamed: 14 spans, scope genkit-tracer, sdk-trace-base 1.25 shape):
- action/flow: genkit:type, genkit:metadata:subtype, genkit:key, genkit:name,
genkit:isRoot (bool), genkit:path, genkit:input, genkit:output,
genkit:state, genkit:metadata:context
- flowStep: genkit:type, genkit:name, genkit:path, genkit:output, genkit:state
- util (generate): genkit:type, genkit:name, genkit:path, genkit:input,
genkit:output, genkit:state
- action/model and action/tool: genkit:type, genkit:metadata:subtype,
genkit:key, genkit:name, genkit:path, genkit:input, genkit:output,
genkit:state
- model genkit:output JSON: message, finishReason, usage {inputTokens,
outputTokens, totalTokens}, latencyMs
- beta agent run adds promptTemplate (render, genkit:metadata:promptName),
flowStep runTurn-1 (genkit:metadata:agent:snapshotId) and action/agent
(genkit:metadata:agent:sessionId, genkit:init); errors add
genkit:isFailureSource.
Kind map from genkit:type labels (core action.ts:538-543, flow.ts:219-221,
ai generate/action.ts:147-149, prompt.ts:273-275,490-492) and the ActionType
list (core registry.ts:40-62): model/background-model LLM, tool/tool.v2 TOOL,
retriever RETRIEVER, embedder EMBEDDING, reranker RERANKER, evaluator
EVALUATOR, agent AGENT, flow and other actions CHAIN, flowStep/util/
promptTemplate/dotprompt CHAIN, unknown type: no kind, span still exported.
Usage: only inputTokens/outputTokens/totalTokens (seen on the dumped model
spans) go to gen_ai.usage.input_tokens/output_tokens/total_tokens, on model
spans only. thoughtsTokens, cachedContentTokens and the character/media
counters exist in GenerationUsageSchema (ai model-types.ts:260-275) but no
inventoried span carried them: unavailable, not mapped. Promoted token/cost
keys on a non-model span move to genkit.usage.<key>; the contract test checks
the trace sum equals the two model calls (32/7/39). Model:
gen_ai.request.model = genkit:name of the model action span (not parsed);
provider and cost unavailable.
Deviations from the TH-8240 architecture/docs, with evidence:
1. enableTelemetry and flushTracing are exported from genkit/tracing
(genkit/src/tracing.ts:43-44), not genkit. genkit/tracing does not
initialise the telemetry provider; importing genkit does
(genkit/src/common.ts:173-175 -> @genkit-ai/core src/node.ts:20-23).
enableTelemetry before any genkit import throws FAILED_PRECONDITION:
TelemetryProvider is not initialized (observed). README says import
genkit first.
2. @genkit-ai/core 1.42.0 telemetryTypes.ts is 24 lines and has only
TelemetryConfig = Partial<NodeSDKConfiguration> (line 24); there is no
TelemetryOptions with forceDevExport / metricExportIntervalMillis /
disableMetrics. Those are @genkit-ai/google-cloud options (src/types.ts:
92,110). The example does not pass disableMetrics (types.test.ts asserts
it is a type error). Metrics are not exported anyway: enableTelemetry adds
no metricReader and @opentelemetry/sdk-node 0.52.1 builds a meter provider
only with a reader or views (build/src/sdk.js:97-105,158). Dev UI export
is not controlled by forceDevExport: Genkit always prepends its
telemetry-server processor.
3. register() must be called with setGlobalTracerProvider: false (the docs
example omits it). fi-core defaults it to true (otel.ts:486,604-605);
Genkit takes its tracer from the global API (instrumentation.ts:96,197),
so with fi-core global the NodeSDK cannot register and Genkit spans reach
Future AGI raw (content, no kind). Contract control test covers this; the
processor emits warning TRACEAI_GENKIT_GLOBAL_PROVIDER.
4. Session: a native key exists for beta agents only,
genkit:metadata:agent:sessionId (ai/src/agent.ts:1061-1063), mapped to
session.id on the agent span. Flows have none; the app sets it with
fi-core setSession() around the call (read in onStart from the parent
context). No session id is invented.
5. Tool name is genkit:name of the tool action span (spec: unverified).
6. AC-06 flush: flushTracing is confirmed (core src/tracing.ts:113). genkit
registers SIGTERM/SIGINT listeners at import that call process.exit(0)
without flushing (genkit/src/genkit.ts:786-793), so an app listener that
awaits flushTracing() loses the race (contract control test). Added
flushOnSignals(flushTracing), which runs the flush before the earlier
listeners.
7. Genkit's NodeSDK uses sdk-trace-base 1.25 spans (parentSpanId,
instrumentationLibrary); fi-core exports with 2.x (parentSpanContext,
instrumentationScope). The processor converts the copy and reads the
fi-core provider's _activeSpanProcessor/_resource (no public accessor).
8. Kinds beyond the spec's list (reranker, evaluator, agent,
background-model, tool.v2, non-action types) come from the inventory.
9. Lockfile: @genkit-ai/core lists @genkit-ai/firebase as an
optionalDependency, so the dev-only tree adds firebase-admin and
@genkit-ai/google-cloud. Neither is a dependency of @traceai/genkit.
pnpm-lock.yaml keeps 3eaadc8 byte for byte plus the new importer and the
177 packages / 180 snapshots reachable from it that the base lacked
(git diff --minimal: 2374 insertions, 0 deletions);
pnpm install --frozen-lockfile (with and without --ignore-scripts)
exits 0: "Lockfile is up to date, resolution step is skipped".
Tests (this tree): jest 5 suites, 62 tests passed (Node 26.8.1, 20.20.2,
22.23.3). Contract suite 20 passed with NODE_BINARY = node 26.8.1, 20.20.2
and 22.23.3. pnpm pack: 63 files, dist/ + README.md + package.json only.
approved: Nikhil 2026-10-03 blanket
Refs: TH-8240
Installed-review N1. Genkit's ValidationError embeds the rejected data in its message after "Provided data:" (@genkit-ai/core 1.42.0 src/schema.ts:78) and instrumentation.ts:156-162 copies e.message to the span status and an exception event on every span the error passes through. The processor passed status and events through unchanged, so with captureContent off (default) a structured ai.generate whose model output fails the schema exported that output to Future AGI. With captureContent off, toExportableSpan now cuts status.message and the exception.message / exception.stacktrace attributes of exception events at "Provided data:" and appends "[data redacted: captureContent is off]". exception.type, the event and every other event are kept. New objects are built; Genkit's span (read by the Dev UI exporter) is not modified. With captureContent true both pass through unchanged. Tests (written first): - jest processor.test.ts: marker in status.message and an exception event, off redacts / on keeps / no-marker unchanged. RED on 24a2929: the off case failed (marker present), 16 others passed. - contract: new `schema` journey (ai.generate with an output schema, the fake mockModel returns non-matching JSON). Asserts the model output text and its marker appear nowhere in the export, both error spans end with the note, exception.type kept ("400", GenkitError.code). RED on 24a2929 (marker found in the exported exception event); opt-in control passed. - GREEN: jest 65 passed; contract 20 passed (Node 26.8.1, no matrix). README: Content table row and paragraph for error-message redaction; the Errors line no longer says status/events pass through unchanged. approved: Nikhil 2026-10-03 blanket Refs: TH-8240
…pans Installed-review N3. isPromotedUsageKey matched only gen_ai.cost.total and llm.cost.total exactly, so cost parts (gen_ai.cost.input/output, llm.cost.prompt/completion) set through fi-core context attributes or Genkit telemetryLabels stayed unprefixed on flow/step/generate/tool spans, where fi-collector would sum them into the trace cost again. Match the cost families by prefix (gen_ai.cost., llm.cost.), like the token families. Model spans keep the keys unprefixed. Tests (written first), mapping.test.ts: - every gen_ai.cost.* / llm.cost.* key is promoted (parts and totals); look-alikes (gen_ai.costs, llm.costing, genkit.usage.*) are not. - cost parts on a flow span, from span and from context attributes, move to genkit.usage.<key>. - a model span keeps them unprefixed (control). RED on b5cb204: the first two failed (2 failed, 37 passed in the file). GREEN: jest 68 passed; contract 20 passed (Node 26.8.1). The contract helper's promoted-key check now uses the same prefixes. README: the promoted-key list names the cost prefixes. approved: Nikhil 2026-10-03 blanket Refs: TH-8240
Installed-review README findings. N4: the Node row claimed the contract suite and import check on 20.20.2, 22.23.3 and 26.8.1, but NODE_BINARY is one Node per run and TRACEAI_NODE_MATRIX parametrizes only the entry-point import check. The full contract suite was rerun once per Node (NODE_BINARY=20.20.2, 22.23.3, 26.8.1; TRACEAI_NODE_MATRIX = all three each time): 22 passed on each at 4973cae. jest also ran once per Node (that Node first on PATH): 68 passed each. The Node row and Tests section now say exactly that, name what TRACEAI_NODE_MATRIX parametrizes, and note the import check uses a symlink, not a clean npm install. N2: new subsection: using the Firebase / Google Cloud telemetry plugin (enableFirebaseTelemetry, enableGoogleCloudTelemetry, ENABLE_FIREBASE_MONITORING) with this package is not supported in this release. Reason: each enableTelemetry() starts another NodeSDK; only the first gets Genkit's spans and flushTracing() flushes only the last. Checked with a local probe (genkit 1.42.0, no plugin, two enableTelemetry calls with recording processors): first processor got the flow span and no flush, second got no span and the flush. Includes the PRD cost note (Future AGI export adds no GCP cost; the GCP copy may be billed by Google). N5: call flushOnSignals after every other SIGTERM/SIGINT listener; later listeners run in parallel with the flush; a second signal is ignored until the flush ends or times out. N6: fi-core TraceConfig / FI_HIDE_* masking is not applied; captureContent is the only content switch. N7: shutdown() also shuts down the register() provider passed in (Genkit's NodeSDK calls it on SIGTERM); use a dedicated provider for Genkit. Docs only; no code or test change. approved: Nikhil 2026-10-03 blanket Refs: TH-8240
…y ordering
verify-r2 (t_f01a72b2) follow-ups:
- validateSupport middleware (Request: <JSON>) and defineSimpleRetriever
(Item: <JSON>) errors carry data without the Provided data: marker and
are exported as thrown; parse-error key paths before the marker stay.
- enableTelemetry({ spanProcessors }) must run before the first Genkit
span, otherwise Genkit's own enableTelemetry({}) wins
(@genkit-ai/core src/tracing.ts:32-40).
N4-r2 is evidence only: coordinator reran jest on Node 20.20.2/22.23.3
(68 passed each) and the full contract with NODE_BINARY 22.23.3 (22 passed),
backing the README Node row as written.
approved: Nikhil 2026-10-03 blanket
Refs: TH-8240
The Google AI / Vertex AI plugin (@genkit-ai/google-genai 1.42.0, lib/googleai/gemini.js:642-646) reports usage.thoughtsTokens and usage.cachedContentTokens. Gemini's outputTokens excludes thinking tokens, so they were only visible inside total_tokens: a real gemini-3.8-flash haiku call exported input 14 / output 12 / total 410 with the 384 thinking tokens unattributed. Map thoughtsTokens to gen_ai.usage.output_tokens.reasoning and cachedContentTokens to gen_ai.usage.cache_read_tokens (model spans only, same as the other usage keys). Verified end to end against a local Future AGI collector with gemini-3.5-flash: 66 + 15 + 39 reasoning = 120 total. README: list the two keys, drop them from the unavailable list, and say the package was also run against the real Google AI plugin. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…I prices them
gen_ai.request.model carried the registered action name
("googleai/gemini-3.5-flash"). fi-collector prices a span by an exact
model-name lookup in its litellm table, which lists "gemini-3.5-flash",
so every Genkit model span showed cost 0 and no provider.
Model spans now get the vendor model id without the plugin namespace on
gen_ai.request.model and gen_ai.response.model, and gen_ai.provider.name
from the namespace for the model plugins whose namespaces were read from
their published packages (googleai -> google, vertexai -> vertexai,
openai, deepseek, xai, anthropic, ollama, mistral -> mistralai, groq,
aws-bedrock -> aws, azure-openai -> azure). Other namespaces leave the
provider unset. The full registered name stays on genkit:name.
Live check with gemini-3.5-flash: model gemini-3.5-flash, provider
google, cost 0.000234 / 0.000357 / 0.000147 in ClickHouse and the UI
(was 0). README: replace the retired gemini-2.5-flash example, document
the provider map and how cost is computed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The catalog rows for all TH-8103 integrations now live in one PR (docs/th-8103-integration-catalog), so this PR no longer conflicts with its siblings in README.md and can merge in any order. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ths, embedder model (TH-8240) Re-verification 2026-10-16 against local Future AGI with real genkit 1.42.0 (latest stable on npm, same as the pin), @genkit-ai/google-genai 1.42.0 (gemini-3.7-flash / gemini-3.8-flash, gemini-embedding-001) and @traceai/fi-core 1.0.0 from npm. Privacy default (TH-8103 coordinator decision 2026-10-16): follow the traceAI TraceConfig convention instead of the package's own captureContent switch. Content is exported by default (fi-core DEFAULT_HIDE_* = false); FI_HIDE_INPUTS / FI_HIDE_OUTPUTS (and FI_HIDE_INPUT_MESSAGES / _OUTPUT_MESSAGES / _INPUT_TEXT / _OUTPUT_TEXT / FI_HIDE_EMBEDDING_VECTORS) or traceConfig hide it, with fi-core's parsing (only "true" hides) and precedence (option > env > default). The env vars apply even when no traceConfig is passed. A hidden side drops the genkit:* content keys and sets input.value / output.value to __REDACTED__ (no mime type), as fi-core's masking does. Passing the removed captureContent option logs a diag warning; captureContent: false still hides inputs and outputs. Never exported, in either mode (the real run on the previous head exported the failing tool's message with the user marker, an email and the absolute working-directory path in status_message, with content "off"): - exception.stacktrace is dropped from every exception event; - stack frames and local paths are removed from every exported string (cwd -> [cwd], home -> ~, other absolute local paths / file URLs / Windows paths -> [path]), JSON-aware; - status message and exception.message lose emails and this machine's user and host names; with inputs or outputs hidden the message becomes "<exception.type>: __REDACTED__" (this replaces the "Provided data:" cut, which only covered schema-validation errors). Embedder spans now carry embedding.model_name (bare id) and gen_ai.provider.name from genkit:name. Tests: jest 95 passed on Node 20.20.2 and 22.18.0; contract suite 22 passed with NODE_BINARY 20.20.2 and 22.18.0 (matrix 20/22). Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
New TypeScript package
@traceai/genkitfor TH-8240 (Firebase Genkit, JS). You passFIGenkitSpanProcessorto Genkit'senableTelemetry({ spanProcessors }).@genkit-ai/corenode-telemetry-provider.ts:66-77), so the Dev UI keeps working.@traceai/fi-coreprovider's processor and OTLP exporter, with the Future AGI resource. Genkit's span is never modified.flushOnSignals(flush)flushes on SIGTERM/SIGINT. Without it, Genkit's own listener exits first and a plain listener never finishes its flush (tested).How spans are mapped:
genkit:typeand the ActionType list (coreregistry.ts:40-62):inputTokens,outputTokens,totalTokens) are mapped, on model spans only. Promoted keys found on non-model spans move togenkit.usage.*.thoughtsTokensandcachedContentTokensexist in the schema but never appeared on a span, so they are recorded as unavailable.gen_ai.request.modelis the model action'sgenkit:name. Provider and cost are not available.genkit:metadata:contextis never exported.session.id;setSessionapplies to flow spans.^1.42.0, Apache-2.0) and a 1.42.0 devDependency only. The tarball holdsdist/, the README andpackage.jsononly (63 files, no*.tsbuildinfo; tested).Deviations from the accepted architecture/docs (with evidence)
enableTelemetryandflushTracingcome fromgenkit/tracing(genkit/src/tracing.ts:43-44), notgenkit.enableTelemetrythrowsFAILED_PRECONDITIONunlessgenkitis imported first (observed). The README says so.disableMetrics/forceDevExportare@genkit-ai/google-cloudoptions, not part ofenableTelemetry's config: core 1.42.0 has onlyTelemetryConfig = Partial<NodeSDKConfiguration>. Metrics are not exported anyway, because no metric reader is set.register()must be called withsetGlobalTracerProvider: false; otherwise Genkit's raw spans also reach Future AGI. The docs example omitted this.The full span inventory (14 spans,
contract/inventory.mjs) and source file:line references are in the commit body. A drift test checks the inventory.Tests (run on f7c6193, clean tree, by the coordinator)
24a2929, and every change is insidetypescript/packages/traceai_genkit.PATH. The 22.23.3 run was at20eea0a;f7c6193changes only the README.pytest typescript/packages/traceai_genkit/contract), withTRACEAI_NODE_MATRIXset to 20/22/26: 22 passed with each ofNODE_BINARY26.8.1, 20.20.2 and 22.23.3. The 22.23.3 run was at20eea0a.Review
Round 1 ran as installed cards on Opus 5.5: pr-reviewer t_6b1ff33d and pr-verifier t_3e78e6b7, which returned CHANGES_REQUESTED. All items are fixed in 24a2929..20eea0a. Swapping the old
processor.ts/attributes.tsin gives 3 jest failures (the new N1 and N3 tests), and the contractschemajourney fails.status.message,exception.messageandexception.stacktraceare cut atProvided data:and end with[data redacted: captureContent is off]. The event andexception.typeare kept; with content on, nothing changes. New contract journey: a structuredgenerategets non-matching JSON from the fake model (b5cb204)20eea0a)gen_ai.cost./llm.cost.(4973cae)20eea0a)FI_HIDE_*, shared-provider shutdown20eea0a)Round 2 was installed pr-verifier t_f01a72b2 at
20eea0a. It confirmed N1, N2, N3 and N5-N7 resolved, with no regressions. On the Firebase auto-init question it agreed with the implementer: auto-init happens only when a span starts beforeenableTelemetry. It checked everyparseSchemapath, andGenkitError.detaildoes not leak. It returned CHANGES_REQUESTED on one evidence gap:NODE_BINARY22.23.3. The README row stands as written.validateSupportmiddleware (Request: <JSON>) anddefineSimpleRetriever(Item: <JSON>) errors as exported as thrown, plus the key paths kept before the marker (f7c6193)enableTelemetryorderingenableTelemetry({})wins (@genkit-ai/coresrc/tracing.ts:32-40)Round 3 (installed pr-verifier t_d5c84073 at
f7c6193) returned VERIFIED, ready to merge. The delta is one commit that changes only the README:validateSupport,defineSimpleRetriever, the key path andenableTelemetryordering match Genkit 1.42.0.Review is complete at
f7c6193. P3 follow-ups after merge:validateSupportmiddleware throughgenkit/middleware, not only a model plugin.20eea0a. The code atf7c6193is identical; only the README changed.npm install. The README discloses this.register({batch:true})does nothing on sdk-trace-base 2.x. That belongs to a separate fi-core ticket.Video demo
Narrated terminal demo, 6:38, recorded at head
f7c6193(the reviewed head), 1080p H.264/AAC, 10 chapters. sha2560b00cf119112ebd9609c27fe1861b4d33a83fbb46995db9d93c01bda192d404f.The video, captions, transcript, chapter list, preview, media check and verification evidence are attached privately to Linear TH-8240 (Future AGI workspace access needed). Every run uses real
genkit1.42.0 with Genkit's mock model, placeholder keys and the shared harness receiver: no vendor call and no live fi-collector.f7c6193: branch, 0 uncommitted files, genkit 1.42.0 (peer^1.42.0), Node 26.8.1, 5 commits on3eaadc8qaFlow=ai.run('prepare')+ai.generatewith toollookup; 7 exports to/tracer/v1/traceswith both auth headers (values not shown); span tree CHAIN / LLM / TOOL; trace tokens 32/7/39 = the two model calls (11/3/14 + 21/4/25), counted once; no token or cost keys on non-LLM spans; content off: 0 of 7 spans with input/output/genkit:input/genkit:output and no markers in the exportsetAttributescost keys, plaingen_ai.cost.*/llm.cost.*stay on the 2 LLM spans and move undergenkit.usage.*on the 5 non-LLM spans; collector-visible cost 0.0092 = 2 calls x 0.0046[data redacted: captureContent is off], with noProvided data:, marker or model JSON; the capture-on control keeps the dataflushOnSignalsall 7 of 7 spans arrive before Genkit's own listener exits; with a plainprocess.on('SIGTERM')listener its flush does not finish before exit, so delivery is a race (2 of 7 arrived on the recorded run, 7 of 7 on the coordinator's driver run; both marked "not guaranteed")src/processor.tsN1 cut andsrc/attributes.tsN3 cost demotionOn-screen waits are trimmed in the edit (disclosed per chapter in the transcript); output is unchanged. Checked by the coordinator: sha256, full decode, chapter markers, no pause of 2.5 s or more, frames per chapter against the driver output, no keys or header values in frames, captions or transcript.
Limits
Stacked on #203 (shared harness). Not merged.
Linear: TH-8240. approved: Nikhil 2026-10-03 blanket
Verification sweep (2026-10-12)
dev, and the spans were checked in ClickHouse and in the Observe UI (hierarchy, span types, input/output, model and tokens, sessions, error status, and a secret scan of everything stored).gen_ai.usage.output_tokens.reasoning,gen_ai.usage.cache_read_tokens), and model spans carry the bare model name plusgen_ai.provider.nameso Future AGI can price them.Re-verification (2026-10-16)
Versions:
genkit1.42.0 (latest stable on npm on 2026-10-16, same as the pin;1.43.0-rc.1not tested),@genkit-ai/google-genai1.42.0,@genkit-ai/compat-oai1.42.0,@traceai/fi-core1.0.0 from npm,@traceai/genkitpacked from this branch. E2E on Node 22.18.0; jest and the contract suite on Node 20.20.2 and 22.18.0.What changed in
506bfeb, and whyTraceConfigconvention (TH-8103 decision of 2026-10-16 for traceAI packages): content is exported by default (fi-coreDEFAULT_HIDE_* = false);FI_HIDE_INPUTS/FI_HIDE_OUTPUTS(andFI_HIDE_INPUT_MESSAGES/_OUTPUT_MESSAGES/_INPUT_TEXT/_OUTPUT_TEXTon model spans,FI_HIDE_EMBEDDING_VECTORSon embedder spans) ortraceConfighide it, with fi-core's parsing and precedence (option > env > default; env applies without atraceConfig). A hidden side drops thegenkit:*content keys and setsinput.value/output.valueto__REDACTED__.captureContentis removed (diag warning;falsestill hides inputs and outputs). This supersedes "Content is off by default" in the Summary above and the README's "captureContent is the only content switch".ed7c58f(content "off") exported the failing tool's message, with the run's marker, an email and the absolute working-directory path, in the span status of 3 spans: theProvided data:cut only covered schema-validation errors. Nowexception.stacktraceis dropped, stack frames and local paths are removed from every exported string (cwd →[cwd], home →~, other absolute local paths →[path], JSON-aware), status message andexception.messagelose emails and the machine's user and host names, and with inputs or outputs hidden the message becomes<exception.type>: __REDACTED__(e.g.Error: __REDACTED__,400: __REDACTED__for a GenkitINVALID_ARGUMENT).embedding.model_name(bare id) andgen_ai.provider.name; both were missing in the real run.FI_HIDE_*hides it and keeps kinds/tokens/model; error type only when hidden; no stack trace, local path, user or host name in any journey): 22 passed withNODE_BINARY20.20.2 and with 22.18.0 (matrix 20/22).E2E against a local Future AGI stack built from
dev(configured exactly as the README:register({ setGlobalTracerProvider: false }),enableTelemetry({ spanProcessors: [new FIGenkitSpanProcessor({ tracerProvider })] }),flushOnSignals(flushTracing), fi-coresetSession/setUseraround each flow). Flows:supportFlow(ai.runstep, real embedder, custom retriever,generatewith toollookupOrder: 2 model calls),streamFlow(generateStream),failingFlow(tool throws,toolChoice: "required").gemini-3.7-flash+gemini-embedding-001, default9f9d8616-37e2-95ba-e8dc-608154b7e317,fdc23b2f-b560-a31e-669a-285cfee6de5a,af62ad95-0cb6-3dfb-1c99-c97eb2adf145(ERROR)FI_HIDE_INPUTS/OUTPUTS/EMBEDDING_VECTORS=true91372b15-6930-9caf-85f2-c8fb1b4a81ef,30a4e115-2c57-5e4d-a665-917597ffa83b,f54dde0c-b2f5-8a8c-0258-128ba3140027(ERROR)gpt-4.1-nano+text-embedding-3-smallvia@genkit-ai/compat-oai, default (live vendor)67ce77eb-43a4-d6c1-3a7a-943ca8f925a2,12891ab0-ca9d-89bf-0bf3-2fa77d06a378,ba54c11d-b626-4e5b-4fbc-de87673a693d(ERROR)c03084e2-b9bc-7b7b-bff1-a18c88c0571d,b2aec706-3138-9077-f005-dee7f40c7a6a,57bb2f46-eb73-ee94-fa3d-e88d4a503eb6(ERROR)2e96ea7c-1a9d-e9a5-3d6d-26123802563fStored-span check (span tree read back from the store; markers masked):
Cost is computed by Future AGI from the bare model name (e.g.
$0.000178/$0.000425for the two Gemini calls in the first trace,$0.0000111for agpt-4.1-nanocall);session.idanduser.idare on every span. The Observe UI shows the tree, kinds, model, provider, tokens, cost, the input/output messages (default) andREDACTEDplusError: __REDACTED__(hidden); checked by eye.Privacy proof. Each run used a fresh unique marker in the prompt, a knowledge-base document, the tool result and the failing tool's error text (plus an email and the working-directory path in that error). Every stored row carrying the project id was scanned (every ClickHouse table with a
project_idcolumn, the Postgres rows):exception.stacktrace, stack frames ornode_modules; the error text reads<email>and[cwd]/billing.json.FI_HIDE_INPUTS+FI_HIDE_OUTPUTS+FI_HIDE_EMBEDDING_VECTORS): 0 hits for the marker, the prompt text, the order id, the tool error text, the answer text, the vector values, and the identity strings above, in both the Gemini and the OpenAI run. Across the whole verification project (125 spans, every run including an intermediate build's and quota-interrupted ones) 0 hits for any hidden run's marker or the identity strings.Limits and notes
429 RESOURCE_EXHAUSTED); the docs page's exact Google AI snippet completed its first model call and the tool call, and the OpenAI variant of the same snippet ran to completion.await flushTracing()comes after it, the process exits on the unhandled rejection and Genkit's error spans (and their parents) are never exported. The docs page flushes infinally.register({ batch: true })is a no-op on sdk-trace-base 2.x (fi-core).Docs page: future-agi/docs#1016 (draft, base
main), suggested nav: Frameworks & Agents → Firebase Genkit (/docs/integrations/traceai/genkit).Merge order unchanged: #203 first (merge commit), the README catalog PR #250 last.
🤖 Generated with Claude Code