@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
179 lines • 7.68 kB
TypeScript
import type { AgentStreamErrorCode } from './stream-events.js';
/** Payloads carried on each `agora:agent:*` channel. */
export interface AgentRunStarted {
runId: string;
threadId: string;
actorId: string;
persona?: string;
}
export interface AgentMessageEvent {
runId: string;
threadId: string;
role: 'user' | 'assistant';
textLength: number;
}
export interface AgentToolCallEvent {
runId: string;
/** The call's id — the same on every publication of it, so an observer can deduplicate. */
toolCallId?: string;
toolName: string;
toolType: 'read' | 'action';
status: string;
/** How long the tool ran, when this process ran it (absent for a decision or a replay). */
durationMs?: number;
/**
* The durable runtime replayed the call's checkpoint instead of running the tool: the call was
* already published by the attempt that ran it. Observers that count calls skip these.
*/
replayed?: boolean;
}
export interface AgentQuotaExceeded {
actorId: string;
usedTokens: number;
limitTokens: number;
}
/**
* Who and what a run is, carried by the run's terminal events so an observer can attribute them
* without reading the store. All optional: a run that has none of them (the default agent, no
* tenant) carries none.
*/
export interface AgentRunContext {
/** The agent that handled the run; absent for the default agent. */
agentName?: string;
actorId?: string;
tenantRef?: string;
/** Set on a delegation's child run: the run that started it. Not a turn of its own. */
parentRunId?: string;
}
export interface AgentRunFinished extends AgentRunContext {
runId: string;
threadId: string;
steps: number;
inputTokens: number;
outputTokens: number;
/** From the turn's start in this process (a resumed run: its resume) to the end. */
durationMs?: number;
/** From the turn's start to the first `text` frame on the stream; absent when no text went out. */
ttftMs?: number;
/** The run's cost, from the steps whose cost is known; absent when none was. */
costUsd?: number;
/** The model of the run's last model call. */
modelId?: string;
}
/**
* A run that ended in an error (the loop threw). `code` is the stable code the stream's `error`
* frame carries ({@link AgentStreamErrorCode}); the error itself is never on the event.
*/
export interface AgentRunFailed extends AgentRunContext {
runId: string;
threadId: string;
code: AgentStreamErrorCode;
/** From the turn's start in this process to the failure. */
durationMs: number;
}
/** A run someone stopped (its abort signal fired) before it finished. */
export interface AgentRunCancelled extends AgentRunContext {
runId: string;
threadId: string;
durationMs: number;
}
export interface AgentDelegated {
runId: string;
fromAgent?: string;
toAgent: string;
/** The delegate was STARTED, not awaited — this run's turn ended without its answer. */
detached?: boolean;
}
export interface AgentRetrieved {
runId: string;
/** Length of the query (not the text) — same redaction posture as {@link AgentMessageEvent}. */
queryLength: number;
count: number;
}
/**
* A transient-classified tool error being retried in place (no new checkpoint) — see
* `invokeWithTransientRetry`. Emitted once per retry (not for the final, non-retried outcome).
*/
export interface AgentToolRetry {
runId: string;
toolName: string;
toolCallId: string;
/** 1-based ordinal of the attempt that just failed and is about to be retried. */
attempt: number;
/** The failed attempt's error message. */
message: string;
}
/** Maps each event name to its payload type, so {@link publishAgent} is checked at the call site. */
export interface AgentDiagnosticPayloads {
'run.started': AgentRunStarted;
message: AgentMessageEvent;
'tool-call': AgentToolCallEvent;
'quota.exceeded': AgentQuotaExceeded;
'run.finished': AgentRunFinished;
'run.failed': AgentRunFailed;
'run.cancelled': AgentRunCancelled;
delegated: AgentDelegated;
retrieved: AgentRetrieved;
'tool.retry': AgentToolRetry;
}
export type AgentDiagnosticEvent = keyof AgentDiagnosticPayloads;
/**
* Publish an agent event on `agora:agent:<event>` via the structural diagnostics slot. No-op when
* diagnostics isn't installed (the slot is empty) — and it never throws back into the agent loop.
*/
export declare function publishAgent<E extends AgentDiagnosticEvent>(event: E, payload: AgentDiagnosticPayloads[E]): void;
export declare function publishAgentRunStarted(payload: AgentRunStarted): void;
export declare function publishAgentMessage(payload: AgentMessageEvent): void;
export declare function publishAgentToolCall(payload: AgentToolCallEvent): void;
export declare function publishAgentQuotaExceeded(payload: AgentQuotaExceeded): void;
export declare function publishAgentRunFailed(payload: AgentRunFailed): void;
export declare function publishAgentRunCancelled(payload: AgentRunCancelled): void;
export declare function publishAgentRunFinished(payload: AgentRunFinished): void;
export declare function publishAgentDelegated(payload: AgentDelegated): void;
export declare function publishAgentRetrieved(payload: AgentRetrieved): void;
export declare function publishAgentToolRetry(payload: AgentToolRetry): void;
/** The root span for a whole agent turn. `run.finished`-shaped summary rides its `asyncEnd`. */
export interface AgentTurnSpan {
runId: string;
}
/** One model call. Summarized (never prompt/output text) with token counts + tool-call count. */
export interface AgentLlmTurnSpan {
runId: string;
step: number;
}
/** One tool invocation. Only the start payload's name/type ride the span — never the tool output. */
export interface AgentToolExecutionSpan {
runId: string;
toolCallId: string;
toolName: string;
toolType: 'read' | 'action' | 'agent';
}
/** One inject-mode retrieval. Query LENGTH (not text) on start; passage `count` on end. */
export interface AgentRetrievalSpan {
runId: string;
queryLength: number;
topK: number;
}
/** Maps each span event to its start payload, so {@link spannedAgent} is checked at the call site. */
export interface AgentSpanPayloads {
turn: AgentTurnSpan;
'llm.turn': AgentLlmTurnSpan;
'tool.execution': AgentToolExecutionSpan;
retrieval: AgentRetrievalSpan;
}
export type AgentSpanEvent = keyof AgentSpanPayloads;
/**
* Wrap a genuinely-executing async operation in an `agora:agent:<event>` span correlated to its run
* by `traceId = runId`, WITHOUT letting the operation's raw return value ride the span envelope: only
* the (redaction-safe) `summarize`d metadata is published as the span `result`, while the real value
* is handed straight back to the caller. Zero-cost when no span sub-channel has a subscriber (runs
* `run()` directly). Never throws from the span machinery — only `run()`'s own rejection propagates.
*
* Mirrors the async lifecycle of `@adonis-agora/diagnostics`' `trace()`: `start` → `end` (sync
* portion) → `asyncStart` → `asyncEnd` (with the summary) on success, or `error` on rejection.
*
* MUST be called from inside a `hooks.step` body (→ `ctx.localStep`) so durable replay — which skips
* step bodies — never re-emits the span. See the module header.
*/
export declare function spannedAgent<E extends AgentSpanEvent, T>(event: E, traceId: string, payload: AgentSpanPayloads[E], run: () => Promise<T>, summarize: (value: T) => Record<string, unknown>): Promise<T>;
//# sourceMappingURL=diagnostics.d.ts.map