Task Evidence API

Session evidence, external files, host spans, HTTP requests, connectivity, and timeline annotations with capture-mode availability.

Use evidence APIs to inspect data retained for the task’s enforced session, capture accessible files, and attach findings to the timeline. A reader being available does not establish that a particular channel was captured. Empty, unknown, unavailable, and truncated results need explicit handling.

Availability by execution mode

APISDK modeDevice modeData or provider requirement
ansight.session.getProperties, getTimelineYesYesProperties and events retained by that session’s provider
ansight.session.getAppStateYesUnavailableLive app-state inspection
ansight.logs, telemetry, artifacts, annotationsYesYesRelevant retained evidence; annotation writes need valid session evidence references
ansight.ui.getVisualTreeSnapshot, searchVisualTreeYesYesRetained visual trees
ansight.screenshots.getFrameYesYesRetained screenshot frames
ansight.network, connectivity, touchesYesUnavailableRelevant HTTP, connectivity, or touch capture
ansight.database.assertYesUnavailableRegistered app database query tool
ansight.filesUnavailableSupported external file provideriOS Simulator containers or accessible Android app data
ansight.spans.measureYesYesHost-observed events around an awaited operation

These are the current task mode restrictions. Other host clients may read imported or completed captures, but tasks start against a live enforced session. Do not infer task availability from a CLI evidence command.

Evidence on virtual and physical devices

SDK capture depends on enabled SDK features and registered tools on either device kind. External capture has a different set of channels:

External evidenceiOS SimulatorPhysical iOSAndroid EmulatorPhysical Android
Screenshots and accessibilityPlatform toolsAppium/XCUITestADB/UIAutomatorADB/UIAutomator
Native app logsUnified logsUnavailableLogcatLogcat
Process CPU and memoryWhen readableOptional Instruments exportWhen readableWhen readable
Rendered FPSUnavailableUnavailableConditional on renderer statisticsConditional on renderer statistics
Private sandbox filesSimulator containersUnavailable for third-party appsrun-as or provisioned root ADBrun-as or provisioned root ADB
Recorded user touches / instrumented HTTPSDK requiredSDK requiredSDK requiredSDK required

See external capture coverage for setup and metric semantics. External automation can send input without recording the user’s touches as an SDK touch stream.

Session, logs, telemetry, and artifacts

Use ansight.session.getTimeline() to correlate categories, ansight.logs to inspect messages and exceptions, ansight.telemetry for samples and summaries, and ansight.artifacts to locate retained snapshots and read their files. The host method index lists each method. ansight.touches analyzes SDK touch evidence; it does not synthesize a touch stream from screenshots. ansight.database.assert queries app-exposed data and needs a named task assertion on its result.

External sandbox files

ansight.files uses the host’s external provider. SDK file tools remain under app.files. Require files.read for list or read, and files.capture for capture.

All three methods take a root-relative path and optional root (default "data"). An empty path lists the root. iOS also supports "app" and "group:<identifier>"; Android supports "data" only. Traversal and symlinks are refused. Android access needs run-as or an already provisioned root ADB daemon.

read returns base64 content and defaults to a maximum of 256 KiB; it cannot exceed that limit. capture defaults to 16 MiB and accepts maximumBytes up to 64 MiB, returning a retained snapshotId. Both return size, SHA-256, provider, timestamps, and consistency: "best-effort-live-copy". The automatic monitor’s exit-copy limit is separately fixed at 16 MiB per file.

Host-observed spans

ansight.spans.measure(name, asyncOperation, { group }?) brackets an operation and emits <name>.started, <name>.completed, or <name>.failed events. It uses two actions and requires host.spans. Use these events as Trends anchors for automation, or native log anchors for flows the app already logs.

Time windows

Network, log, telemetry, touch, annotation, artifact, and timeline methods accept their typed argument contracts from ansight-task.d.ts. Time-bound contracts use ISO-8601 UTC timestamps and bounded result limits. Prefer typed methods over ansight.callTool because they inject the task session and return stable named contracts.

Connectivity uses its own from, to, and at fields, which also accept offsets from capture start. Its cursor behavior differs from HTTP pagination; see the next section before sharing query helpers across these APIs.

Connectivity evidence

ansight.connectivity reads captured OS connection state, changes, quality samples, and observation gaps. These task methods currently require SDK mode and relevant connectivity capture. The host can also inspect imported captures through other clients; that does not allow starting a task against an offline session.

MethodUseResult
ansight.connectivity.summary(args?)Summarize a capture windowAvailability durations, changes, disconnections, reconnections, gaps, quality samples and transports
ansight.connectivity.timeline(args?)Page through captured recordsMatching records, counts, hasMore, and nextCursor
ansight.connectivity.at(args)Inspect state at a time or annotationObserved state, availability, and measurement age; requires at or annotationId

All return ConnectivityResult, including captured, recordCount, malformedRecordCount, supportedMeasurements, effective capture/window bounds, and rangeClipped. captured: false or availability: "unknown" is not proof that the device was offline. A gap means observation was interrupted.

Arguments are from, to, at, annotationId, beforeSeconds, afterSeconds, kind, limit, and cursor. Times accept ISO-8601 or mm:ss / hh:mm:ss offsets from capture start. An annotation supplies a default window of 120 seconds before and 30 seconds after it; either padding accepts 1–3,600 seconds. kind filters snapshot, change, quality, or gap. The default limit is 200; the maximum is 1,000.

const state = await ansight.connectivity.at({ at: "00:30" });
expect(state.captured, { id: "connectivity-was-captured" }).toBe(true);
expect(state.availability, { id: "connection-at-checkpoint" }).toBe("available");

Choose a checkpoint established by the workflow. OS connection availability does not prove that a particular server was reachable or a request succeeded; correlate with the HTTP request evidence below. Quality fields and transports depend on the platform and enabled SDK feature. See SDK connectivity capture.

For timeline pagination, repeat the same filters with cursor: nextCursor. A changed live capture invalidates its cursor; start a new query if necessary. HTTP cursors instead retain a fixed matching snapshot. at() can return unknown when no observation covers the requested time; inspect measurement age before relying on an old quality sample.

Connectivity inspection does not change the network. To apply TCP rate, stall, or delay conditions use ansight.device.network.

Captured network requests

ansight.network inspects HTTP capture records already received by the task’s session. Its standard methods require no task.hostTools declaration. Calls must be awaited serially, like other host methods.

const failures = await ansight.network.get({
  methods: ["POST"],
  query: "/checkout",
  failedOnly: true,
  limit: 20
});

const first = failures.requests[0];
if (first) {
  const detail = await ansight.network.getRequest({ requestId: first.id });
  const response = await ansight.network.readBody({
    requestId: first.id,
    side: "response",
    maxBytes: 16 * 1024
  });

  // Header arrays preserve duplicate names; body content stays separately bounded.
  console.log(detail.request.responseHeaders, detail.headersTruncated);
  if (response.body !== null) {
    console.log(response.body.encoding, response.body.data);
  }
}

get accepts inclusive request-start startUtc/endUtc bounds, methods, statuses, host, query, failedOnly, limit, and cursor. Different filters combine with AND; values within methods or statuses combine with OR. Empty arrays impose no restriction. Methods, hostname substrings, and text queries are case-insensitive. Statuses accept integer codes from 100 through 599 or "1xx" through "5xx". query searches URL, method, and error message. failedOnly: true includes transport errors and HTTP statuses of at least 400; false imposes no restriction. Invalid dates, reversed time ranges, and invalid filters reject the call.

Pages contain complete summaries without header values or body content, ordered newest first with a request-ID tie-breaker. The default limit is 200 and the maximum is 1,000; the output budget can reduce the actual page size. Continue with get({ cursor: page.nextCursor }) after checking nextCursor is non-null. Cursors retain the initial matching snapshot, so live arrivals do not shift subsequent pages. The same filters may be repeated, but conflicting filters, a different session, or an expired cursor reject. Snapshots expire five minutes after creation and may be evicted earlier by the bounded host cache (32 snapshots, 16 Mi characters of summary data). After expiry or eviction, start a new query without a cursor; this also includes new arrivals. A matching snapshot that exceeds the cache budget rejects with a request to narrow the filters. matchedRequestCount describes the snapshot and isTruncated means matching records remain after the page.

getRequest rejects unknown request IDs and returns metadata plus bounded request/response header arrays. headersTruncated reports omitted complete entries. readBody rejects unknown request IDs, but returns body: null when the selected request has no retained body. A captured empty body instead has data: "" and returnedByteCount: 0. Missing capture data does not explain why content is unavailable.

maxBytes bounds decoded bytes, defaults to 16 KiB, and accepts 1 through 64 KiB. Reads return a prefix that preserves UTF-8 boundaries; binary content uses Base64. encoding identifies the representation, while capturedBytes, totalBytes, and returnedByteCount distinguish capture metadata from this read. truncated means capture omitted content; isTruncated means the read omitted retained content. Both must be false for a complete body. Capture sanitization is preserved, and body content is not automatically parsed as JSON. Metadata, headers, and body previews are subject to the host’s serialized output budget; an individual summary that cannot fit rejects explicitly.

Empty results do not prove capture is enabled or that an in-flight request has completed. These methods inspect retained traffic; they do not initiate, replay, intercept, or mock requests. Correlate network records with other evidence using ansight.session.getTimeline({ categories: ["networkRequest"] }).

Timeline and screenshot annotations

An annotation has a timeline point or range and may include screenshot shapes and a semantic visual-tree target. ansight.annotations.get(args?) keeps its existing time, label, frameId, and hasGeometry filters. create, update, and delete operate within the same enforced session and require no extra host tool declarations.

const created = await ansight.annotations.create({
  label: "Checkout failed",
  startUtc: failedRequest.startedAtUtc,
  endUtc: failedRequest.completedAtUtc,
  notes: `${failedRequest.method} ${failedRequest.url}`,
  geometries: [{
    kind: "rectangle",
    frameId: inspectedFrame.frameId,
    x: 0.1, y: 0.65, width: 0.8, height: 0.12
  }]
});

await ansight.annotations.update({
  annotationId: created.annotationId,
  expectedSource: created.annotation.source,
  notes: "Response body reviewed.",
  endUtc: null
});

// Remove the annotation if the task no longer needs it.
await ansight.annotations.delete({ annotationId: created.annotationId });

The example assumes the request and screenshot were inspected earlier in the task; its coordinates are illustrative. Derive real shapes from the selected frame. Annotation writes preserve evidence but do not establish task success; use a named expect assertion after writing failure evidence.

create requires a non-whitespace label; it accepts optional annotationId, notes, source, startUtc, endUtc, geometries, and target. It generates an ID when omitted and atomically rejects an existing explicit ID. The default source is task:<taskId>. An omitted start uses the session’s latest captured timestamp; supply an evidence timestamp for reproducible placement. A generated ID is not an idempotency key: reconcile an uncertain create before retrying.

update patches the latest saved record atomically. Omitted fields remain unchanged. null clears notes, endUtc, or target; geometries: [] clears shapes; a supplied geometry array replaces the entire array. Empty notes normalize to no notes. Source, capture group, custom data, attached evidence, and hook failures are preserved. The resulting end cannot precede its start, and equality normalizes to a point. Timeline edits preserve actual screenshot capture times. A no-op update succeeds and returns the saved record.

update and delete require an existing annotationId. Their optional expectedSource is an exact-match guard checked atomically with the mutation; a mismatch rejects without changing the record. This guard checks provenance, not a revision. Concurrent patches preserve omitted fields; competing edits to a supplied field use the last write. Mutations return the saved normalized annotation, or deletedAnnotation after deletion. If the full saved or deleted record exceeds 480,000 serialized characters, the call rejects before mutating state. Existing host and CLI annotation operations remain available for large legacy records.

Geometry inputs are typed point, rectangle, ellipse, or freeDraw records, anchored by frameId. Coordinates are finite and normalized from 0 to 1 over the full screenshot. Boxes need positive dimensions and must fit within the image; free-draw paths need at least two points. Invalid geometry and styles reject. The host resolves the frame’s capture timestamp and derives free-draw bounds. Optional geometry fields are geometryId, text, strokeColor, and strokeWidth. Stroke colors accept #RRGGBB or #AARRGGBB; stroke width must be finite and positive.

A semantic target is { visualTreeSnapshotId, nodeId } from an inspected, retained visual-tree snapshot. The host resolves its label, type, automation ID, and bounds, and returns the node identity as target.targetId. Both frames and trees must belong to the enforced session; references never silently capture new evidence. Read results provide named geometry, target, inferred-shape, and attached-evidence types. Output geometries also describe legacy line and arrow shapes created by other host clients.