agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
130 lines • 5.82 kB
TypeScript
/**
* xrayObservability — AWS X-Ray distributed-tracing adapter.
*
* Maps agentfootprint's event taxonomy onto AWS X-Ray segment trees:
*
* agent.turn_start ↦ root segment (one trace per turn)
* agent.turn_end ↦ close root segment + flush
* agent.iteration_start ↦ push subsegment under root
* agent.iteration_end ↦ close iteration subsegment
* stream.llm_start ↦ push leaf subsegment (model call)
* stream.llm_end ↦ close llm subsegment
* stream.tool_start ↦ push leaf subsegment (tool call)
* stream.tool_end ↦ close tool subsegment (correlated
* by toolCallId — parallel-safe)
* a bracket carrying ↦ nothing: the call never executed
* `notDispatched` (9.113.0), so no subsegment opens or
* closes for it. Moot today: a trace
* opens on `agent.turn_start` only, a
* resumed leg emits none and carries a
* new `meta.runId`, so none of it is
* traced — and a settled bracket only
* ever rides a resumed leg
* error.fatal ↦ fault on root + close the whole
* tree (turn_end never arrives)
*
* Events are anchored on `meta.runId` (the dispatcher envelope),
* with a `payload.runId` fallback for hand-built events.
*
* The result in the X-Ray Trace Map: a hierarchical timeline of every
* agent run — turn → iteration → llm-call/tool-call — queryable in
* X-Ray Insights, joinable with the rest of your AWS distributed
* trace via `AWSTraceHeader` propagation (consumer's responsibility
* to wire upstream/downstream IDs).
*
* Subpath: `agentfootprint/observe`
* Peer dep: `@aws-sdk/client-xray` (OPTIONAL — installed only when
* this adapter is used).
*
* Sampling:
* By default every turn produces one trace. Pass `sampleRate: 0.1`
* to sample 10% of turns — sampling decisions are made at
* `turn_start` and persist for the whole turn (so partial traces
* never reach X-Ray).
*
* @example
* ```ts
* import { xrayObservability } from 'agentfootprint/observe';
* import { microtaskBatchDriver } from 'footprintjs/detach';
*
* agent.enable.observability({
* strategy: xrayObservability({
* region: 'us-east-1',
* serviceName: 'my-agent',
* sampleRate: 0.1, // 10% sampling
* }),
* detach: { driver: microtaskBatchDriver, mode: 'forget' },
* });
* ```
*
* @example Test injection
* ```ts
* xrayObservability({
* serviceName: 'test',
* _client: {
* putTraceSegments: async (input) => { capturedDocs.push(input); },
* },
* });
* ```
*/
import type { AgentfootprintEvent } from '../../events/registry.js';
import type { ObservabilityStrategy } from '../../strategies/types.js';
export interface XrayObservabilityOptions {
/** AWS region. Falls back to AWS_REGION / AWS_DEFAULT_REGION env. */
readonly region?: string;
/** Service name on every emitted segment. Surfaces in X-Ray's
* service map. Required. */
readonly serviceName: string;
/** 0..1 — fraction of turns to sample. Default `1.0` (every turn).
* Decisions are made at `turn_start` and persist for the whole
* turn so partial traces never reach X-Ray. */
readonly sampleRate?: number;
/** Max segments buffered before forced flush. X-Ray's
* `PutTraceSegments` API accepts up to 50 segments per call;
* default 25 keeps latency tight. */
readonly maxBatchSegments?: number;
/** Forced flush window for low-traffic agents. Default 1000ms.
* `0` disables time-based flush. */
readonly flushIntervalMs?: number;
/**
* Where delivery failures go (8.11.0).
*
* `PutTraceSegments` is network I/O and it fails — an IAM denial, a
* throttle, a malformed segment. Without this, failures reach the default
* sink (a rate-limited `console.error`), because telemetry that fails
* invisibly is indistinguishable from telemetry that works. Set this to
* route them into your own logger instead; you receive every failure. The
* batch that failed is dropped, never requeued.
*
* Equivalent to assigning the strategy's `_onError` property after
* construction, but visible at the call site.
*/
readonly onError?: (error: Error, event?: AgentfootprintEvent) => void;
/** Test injection — bypasses SDK lazy-require entirely. */
readonly _client?: XRayLikeClient;
/** @internal Test injection (9.4.0) — the AWS SDK module, so the real shim
* (`send(new Command(...))`) runs against a fake SDK and the command name it
* dispatches can be asserted. Ignored when `_client` is set. */
readonly _sdk?: XRaySdkModule;
}
export interface XRayLikeClient {
putTraceSegments(input: {
TraceSegmentDocuments: ReadonlyArray<string>;
}): Promise<unknown>;
}
/**
* The slice of `@aws-sdk/client-xray` this shim touches.
*
* Exported since 9.4.0 so `opts._sdk` can name it — which is what lets the
* shared command-name pin (test/adapters/aws/) assert that this adapter
* dispatches `PutTraceSegments` and nothing invented, without an AWS account
* or the peer dep installed.
*/
export interface XRaySdkModule {
readonly XRayClient?: new (config: {
region?: string;
}) => unknown;
readonly PutTraceSegmentsCommand?: new (input: unknown) => unknown;
}
export declare function xrayObservability(opts: XrayObservabilityOptions): ObservabilityStrategy;
//# sourceMappingURL=xray.d.ts.map