@temporalio/agent-harness 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -2
  3. package/dist/src/ai-sdks/google-genai-plugin/index.d.ts +6 -0
  4. package/dist/src/ai-sdks/google-genai-plugin/index.js +24 -0
  5. package/dist/src/ai-sdks/google-genai-plugin/interactions-conversation.d.ts +35 -0
  6. package/dist/src/ai-sdks/google-genai-plugin/interactions-conversation.js +178 -0
  7. package/dist/src/ai-sdks/google-genai-plugin/interactions-models.d.ts +8 -0
  8. package/dist/src/ai-sdks/google-genai-plugin/interactions-models.js +4 -0
  9. package/dist/src/ai-sdks/google-genai-plugin/interactions-workflow.d.ts +8 -0
  10. package/dist/src/ai-sdks/google-genai-plugin/interactions-workflow.js +15 -0
  11. package/dist/src/ai-sdks/google-genai-plugin/temporal-async-client.d.ts +10 -0
  12. package/dist/src/ai-sdks/google-genai-plugin/temporal-async-client.js +9 -0
  13. package/dist/src/ai-sdks/google-genai-plugin/temporal-interactions.d.ts +31 -0
  14. package/dist/src/ai-sdks/google-genai-plugin/temporal-interactions.js +43 -0
  15. package/dist/src/ai-sdks/google-genai-plugin/workflow.d.ts +16 -0
  16. package/dist/src/ai-sdks/google-genai-plugin/workflow.js +14 -0
  17. package/dist/src/ai-sdks/jev/evaluator.d.ts +38 -0
  18. package/dist/src/ai-sdks/jev/evaluator.js +155 -0
  19. package/dist/src/ai-sdks/openai-agents-harness.d.ts +94 -0
  20. package/dist/src/ai-sdks/openai-agents-harness.js +347 -0
  21. package/dist/src/harness/agent-protocol/agent-interface.d.ts +369 -0
  22. package/dist/src/harness/agent-protocol/agent-interface.js +222 -0
  23. package/dist/src/harness/agent-protocol/events.d.ts +10 -0
  24. package/dist/src/harness/agent-protocol/events.js +6 -0
  25. package/dist/src/harness/agent-protocol/index.d.ts +5 -0
  26. package/dist/src/harness/agent-protocol/index.js +7 -0
  27. package/dist/src/harness/agent-protocol/schema.d.ts +34 -0
  28. package/dist/src/harness/agent-protocol/schema.js +53 -0
  29. package/dist/src/harness/agent-protocol/subagent-interface.d.ts +25 -0
  30. package/dist/src/harness/agent-protocol/subagent-interface.js +17 -0
  31. package/dist/src/harness/agent-schema.d.ts +4 -0
  32. package/dist/src/harness/agent-schema.js +106 -0
  33. package/dist/src/harness/agent-workflow/errors.d.ts +26 -0
  34. package/dist/src/harness/agent-workflow/errors.js +67 -0
  35. package/dist/src/harness/agent-workflow/types.d.ts +88 -0
  36. package/dist/src/harness/agent-workflow/types.js +1 -0
  37. package/dist/src/harness/agent-workflow.d.ts +79 -0
  38. package/dist/src/harness/agent-workflow.js +824 -0
  39. package/dist/src/harness/agent.d.ts +137 -0
  40. package/dist/src/harness/agent.js +272 -0
  41. package/dist/src/harness/code-mode/activity-fs.d.ts +46 -0
  42. package/dist/src/harness/code-mode/activity-fs.js +102 -0
  43. package/dist/src/harness/code-mode/base64.d.ts +2 -0
  44. package/dist/src/harness/code-mode/base64.js +41 -0
  45. package/dist/src/harness/code-mode/driver.d.ts +78 -0
  46. package/dist/src/harness/code-mode/driver.js +266 -0
  47. package/dist/src/harness/code-mode/index.d.ts +4 -0
  48. package/dist/src/harness/code-mode/index.js +6 -0
  49. package/dist/src/harness/code-mode/mount-decl.d.ts +43 -0
  50. package/dist/src/harness/code-mode/mount-decl.js +100 -0
  51. package/dist/src/harness/code-mode/okf-tool.d.ts +10 -0
  52. package/dist/src/harness/code-mode/okf-tool.js +89 -0
  53. package/dist/src/harness/code-mode/okf.d.ts +91 -0
  54. package/dist/src/harness/code-mode/okf.js +315 -0
  55. package/dist/src/harness/code-mode/stubs.d.ts +13 -0
  56. package/dist/src/harness/code-mode/stubs.js +203 -0
  57. package/dist/src/harness/code-mode/texts.d.ts +4 -0
  58. package/dist/src/harness/code-mode/texts.js +6 -0
  59. package/dist/src/harness/code-mode/tool.d.ts +37 -0
  60. package/dist/src/harness/code-mode/tool.js +79 -0
  61. package/dist/src/harness/code-mode/vfs.d.ts +209 -0
  62. package/dist/src/harness/code-mode/vfs.js +862 -0
  63. package/dist/src/harness/py-repr.d.ts +2 -0
  64. package/dist/src/harness/py-repr.js +24 -0
  65. package/dist/src/harness/state/index.d.ts +40 -0
  66. package/dist/src/harness/state/index.js +142 -0
  67. package/dist/src/harness/stream-context.d.ts +8 -0
  68. package/dist/src/harness/stream-context.js +9 -0
  69. package/dist/src/harness/subagent-toolset.d.ts +29 -0
  70. package/dist/src/harness/subagent-toolset.js +87 -0
  71. package/dist/src/index.d.ts +12 -0
  72. package/dist/src/index.js +13 -0
  73. package/dist/src/sandbox.d.ts +12 -0
  74. package/package.json +95 -3
@@ -0,0 +1,53 @@
1
+ // Schemas: any Standard Schema that can also render JSON Schema (zod v4 is one), or raw JSON
2
+ // Schema wrapped with `jsonSchema()`. The harness needs JSON Schema for agent_interface, model
3
+ // tool declarations and Code Mode stubs, and synchronous validation (update validators are sync).
4
+ // TypeScript only: Python's models are pydantic's, which carry both.
5
+ /**
6
+ * JSON Schema of a schema: what it accepts (`input`, the default) or what parsing returns (`output`).
7
+ * zod renders each mode as it behaves: an input object is open, since parsing ignores extra keys,
8
+ * and an output object is closed.
9
+ */
10
+ export function toJsonSchema(schema, io = "input") {
11
+ const libraryOptions = { unrepresentable: "any" };
12
+ const { $schema: _drop, ...rest } = schema["~standard"].jsonSchema[io]({
13
+ target: "draft-2020-12",
14
+ libraryOptions,
15
+ });
16
+ return rest;
17
+ }
18
+ /** Validate synchronously; schemas with async refinements are rejected. */
19
+ export function validate(schema, value) {
20
+ const result = schema["~standard"].validate(value);
21
+ if (result instanceof Promise)
22
+ throw new TypeError("harness schemas must validate synchronously");
23
+ if (result.issues === undefined)
24
+ return { ok: true, value: result.value };
25
+ return {
26
+ ok: false,
27
+ message: result.issues
28
+ .map((i) => (i.path?.length
29
+ ? `${i.path.map((p) => String(typeof p === "object" ? p.key : p)).join(".")}: `
30
+ : "") + i.message)
31
+ .join("; "),
32
+ };
33
+ }
34
+ /**
35
+ * Raw JSON Schema as a harness schema (the AI SDK's `jsonSchema()` counterpart). Values pass
36
+ * unchecked unless `validate` is given, so prefer a schema library where input is untrusted.
37
+ */
38
+ export function jsonSchema(schema, options = {}) {
39
+ const render = () => schema;
40
+ return {
41
+ "~standard": {
42
+ version: 1,
43
+ vendor: "temporal-agent-harness",
44
+ validate(value) {
45
+ if (options.validate === undefined)
46
+ return { value: value };
47
+ const r = options.validate(value);
48
+ return r.ok ? { value: r.value } : { issues: [{ message: r.message }] };
49
+ },
50
+ jsonSchema: { input: render, output: render },
51
+ },
52
+ };
53
+ }
@@ -0,0 +1,25 @@
1
+ import { z } from "zod";
2
+ export declare const RUN_SUBAGENT_TURN_ACTIVITY = "run_subagent_turn";
3
+ export declare const DEFAULT_SUBAGENT_HEARTBEAT_TIMEOUT = "20 seconds";
4
+ export declare const DEFAULT_SUBAGENT_START_TO_CLOSE_TIMEOUT = "1 hour";
5
+ export declare const RunSubagentTurnInputSchema: z.ZodObject<{
6
+ child_workflow_id: z.ZodString;
7
+ type: z.ZodString;
8
+ payload: z.ZodDefault<z.ZodCustom<Record<string, unknown>, Record<string, unknown>>>;
9
+ from_offset: z.ZodDefault<z.ZodNumber>;
10
+ handle: z.ZodString;
11
+ agent_key: z.ZodString;
12
+ parent_stream_context: z.ZodObject<{
13
+ turn_id: z.ZodString;
14
+ turn_number: z.ZodNumber;
15
+ message_id: z.ZodDefault<z.ZodNullable<z.ZodString>>;
16
+ agent_id: z.ZodString;
17
+ }, z.core.$strip>;
18
+ }, z.core.$strip>;
19
+ export type RunSubagentTurnInput = z.output<typeof RunSubagentTurnInputSchema>;
20
+ export interface SubagentTurnResult {
21
+ output: Record<string, unknown>;
22
+ turn_id: string;
23
+ turn_number: number;
24
+ consumed_offset: number;
25
+ }
@@ -0,0 +1,17 @@
1
+ // The subagent-turn activity contract between a parent agent's workflow and the harness activity
2
+ // that drives one turn on a child (Python's agent_protocol/subagent_interface.py).
3
+ import { z } from "zod";
4
+ import { messagePayload } from "./agent-interface.js";
5
+ import { TurnStreamContextSchema } from "../stream-context.js";
6
+ export const RUN_SUBAGENT_TURN_ACTIVITY = "run_subagent_turn";
7
+ export const DEFAULT_SUBAGENT_HEARTBEAT_TIMEOUT = "20 seconds";
8
+ export const DEFAULT_SUBAGENT_START_TO_CLOSE_TIMEOUT = "1 hour";
9
+ export const RunSubagentTurnInputSchema = z.object({
10
+ child_workflow_id: z.string(),
11
+ type: z.string(),
12
+ payload: messagePayload,
13
+ from_offset: z.number().int().default(0),
14
+ handle: z.string(),
15
+ agent_key: z.string(),
16
+ parent_stream_context: TurnStreamContextSchema,
17
+ });
@@ -0,0 +1,4 @@
1
+ import type { AgentWorkflow } from "./agent.ts";
2
+ type Json = Record<string, unknown>;
3
+ export declare function agentSchema(agent: AgentWorkflow, source: string): Json;
4
+ export {};
@@ -0,0 +1,106 @@
1
+ // `temporal-agent-harness schema`: an agent's init data, handlers and observable state as one JSON
2
+ // Schema document, in the shape @temporal-agent-harness/codegen consumes. Each model becomes a
3
+ // `$defs` entry named by its zod `.meta({ title })`, else by where it appears; a titled object
4
+ // nested inside one gets its own entry too. Init data and handler inputs are in input mode (a
5
+ // defaulted field may be omitted by a sender); handler outputs and states in output mode (every
6
+ // field arrives). A model whose two modes differ appears as `Name-Input` and `Name-Output`, as
7
+ // pydantic names them.
8
+ import { toJsonSchema } from "./agent-protocol/index.js";
9
+ // Refs are written as `PENDING name \0 io` and resolved once every model has been seen, because
10
+ // whether a name splits into -Input/-Output depends on all of them.
11
+ const PENDING = "\0pending:";
12
+ const isObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
13
+ const LITERAL_KEYS = new Set(["default", "const", "enum", "examples"]);
14
+ export function agentSchema(agent, source) {
15
+ const def = agent.definition;
16
+ const found = new Map();
17
+ const owners = new Map();
18
+ const register = (name, io, body) => {
19
+ const modes = found.get(name) ?? {};
20
+ const prior = modes[io];
21
+ if (prior !== undefined && JSON.stringify(prior) !== JSON.stringify(body))
22
+ throw collision(name);
23
+ found.set(name, { ...modes, [io]: body });
24
+ return { $ref: `${PENDING}${name}\0${io}` };
25
+ };
26
+ const collision = (name) => new Error(`${def.name}: two different models are both named '${name}'; give each a unique .meta({ title })`);
27
+ const hoist = (node, io, top) => {
28
+ if (Array.isArray(node))
29
+ return node.map((n) => hoist(n, io, false));
30
+ if (!isObject(node))
31
+ return node;
32
+ const out = Object.fromEntries(Object.entries(node).map(([k, v]) => [k, LITERAL_KEYS.has(k) ? v : hoist(v, io, false)]));
33
+ return !top && typeof out.title === "string" && out.type === "object"
34
+ ? register(out.title, io, out)
35
+ : out;
36
+ };
37
+ // zod's own `$defs` (a recursive model's) are lifted as they are, so their refs still resolve.
38
+ const lifted = {};
39
+ const ref = (schema, io, fallback) => {
40
+ const { $defs: inner = {}, ...generated } = toJsonSchema(schema, io);
41
+ for (const [key, value] of Object.entries(inner)) {
42
+ if (key in lifted && JSON.stringify(lifted[key]) !== JSON.stringify(value))
43
+ throw collision(key);
44
+ lifted[key] = value;
45
+ }
46
+ const body = hoist(generated, io, true);
47
+ const name = typeof body.title === "string" ? body.title : fallback;
48
+ const seen = owners.get(name) ?? new Set();
49
+ if (seen.add(schema).size > 1)
50
+ throw collision(name);
51
+ owners.set(name, seen);
52
+ return register(name, io, body);
53
+ };
54
+ const pascal = (s) => s.replace(/(^|_)(\w)/g, (_m, _p, c) => c.toUpperCase());
55
+ const doc = {
56
+ agent: def.name,
57
+ source,
58
+ init_data: def.initData === undefined
59
+ ? null
60
+ : {
61
+ data: ref(def.initData.schema, "input", `${def.name}InitData`),
62
+ required: def.initData.required,
63
+ },
64
+ handlers: Object.fromEntries(Object.entries(def.handlers)
65
+ .sort(([a], [b]) => a.localeCompare(b))
66
+ .map(([name, h]) => [
67
+ name,
68
+ {
69
+ description: h.description,
70
+ mid_turn: h.midTurn,
71
+ input: ref(h.input, "input", `${pascal(name)}Input`),
72
+ output: ref(h.output, "output", `${pascal(name)}Output`),
73
+ },
74
+ ])),
75
+ states: Object.fromEntries(Object.entries(def.states ?? {}).map(([id, decl]) => [
76
+ id,
77
+ ref(decl.schema, "output", pascal(id)),
78
+ ])),
79
+ };
80
+ const split = new Set([...found]
81
+ .filter(([, m]) => m.input && m.output && JSON.stringify(m.input) !== JSON.stringify(m.output))
82
+ .map(([n]) => n));
83
+ const defs = { ...lifted };
84
+ for (const [name, { input, output }] of found) {
85
+ if (split.has(name))
86
+ Object.assign(defs, { [`${name}-Input`]: input, [`${name}-Output`]: output });
87
+ else
88
+ defs[name] = input ?? output;
89
+ }
90
+ doc.$defs = Object.fromEntries(Object.entries(defs).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)));
91
+ const resolve = (node) => {
92
+ if (Array.isArray(node))
93
+ return node.map(resolve);
94
+ if (!isObject(node))
95
+ return node;
96
+ if (typeof node.$ref === "string" && node.$ref.startsWith(PENDING)) {
97
+ const [name = "", io] = node.$ref.slice(PENDING.length).split("\0");
98
+ return {
99
+ ...node,
100
+ $ref: `#/$defs/${split.has(name) ? `${name}-${io === "input" ? "Input" : "Output"}` : name}`,
101
+ };
102
+ }
103
+ return Object.fromEntries(Object.entries(node).map(([k, v]) => [k, LITERAL_KEYS.has(k) ? v : resolve(v)]));
104
+ };
105
+ return resolve(doc);
106
+ }
@@ -0,0 +1,26 @@
1
+ import type { AutoModeEvaluator, ToolApprovalPolicy } from "../agent-protocol/index.ts";
2
+ export declare class ToolApprovalDenied extends Error {
3
+ name: string;
4
+ readonly toolName: string;
5
+ readonly reason: string | null;
6
+ constructor(toolName: string, reason: string | null);
7
+ }
8
+ export declare class CallbackToolError extends Error {
9
+ name: string;
10
+ readonly toolName: string;
11
+ readonly reason: string | null;
12
+ constructor(toolName: string, reason: string | null);
13
+ }
14
+ /** What Python's `str(e)` gives for an exception: its message alone. */
15
+ export declare function errorMessage(e: unknown): string;
16
+ /**
17
+ * Whether `e` is the cancellation of the scope this code runs in (Python's CancelledError, which
18
+ * `except Exception` lets through), not a cancellation it observed from an inner scope, such as an
19
+ * author's own timeout, which is a failure like any other.
20
+ */
21
+ export declare function isOwnCancellation(e: unknown): boolean;
22
+ /** An error and its causes, deduplicated: an ActivityFailure's own message says only "Activity task failed". */
23
+ export declare function errorText(e: unknown): string;
24
+ /** Rejects JSON a Python peer can't read back as sent. */
25
+ export declare function assertPortableJson(value: unknown, what: string): void;
26
+ export declare function assertAutoModeHasEvaluator(policy: ToolApprovalPolicy, evaluator: AutoModeEvaluator | undefined): void;
@@ -0,0 +1,67 @@
1
+ import { ApplicationFailure, CancellationScope, isCancellation } from "@temporalio/workflow";
2
+ import { portabilityProblem } from "../state/index.js";
3
+ export class ToolApprovalDenied extends Error {
4
+ name = "ToolApprovalDenied";
5
+ toolName;
6
+ reason;
7
+ constructor(toolName, reason) {
8
+ super(`tool '${toolName}' was not approved${reason ? `: ${reason}` : ""}`);
9
+ this.toolName = toolName;
10
+ this.reason = reason;
11
+ }
12
+ }
13
+ export class CallbackToolError extends Error {
14
+ name = "CallbackToolError";
15
+ toolName;
16
+ reason;
17
+ constructor(toolName, reason) {
18
+ super(`callback tool '${toolName}' failed${reason ? `: ${reason}` : ""}`);
19
+ this.toolName = toolName;
20
+ this.reason = reason;
21
+ }
22
+ }
23
+ /** What Python's `str(e)` gives for an exception: its message alone. */
24
+ export function errorMessage(e) {
25
+ return e instanceof Error ? e.message : String(e);
26
+ }
27
+ /**
28
+ * Whether `e` is the cancellation of the scope this code runs in (Python's CancelledError, which
29
+ * `except Exception` lets through), not a cancellation it observed from an inner scope, such as an
30
+ * author's own timeout, which is a failure like any other.
31
+ */
32
+ export function isOwnCancellation(e) {
33
+ return isCancellation(e) && CancellationScope.current().consideredCancelled;
34
+ }
35
+ /** An error and its causes, deduplicated: an ActivityFailure's own message says only "Activity task failed". */
36
+ export function errorText(e) {
37
+ const parts = [];
38
+ let current = e;
39
+ while (current instanceof Error && parts.length < 5) {
40
+ const text = current.message || current.name;
41
+ if (!parts.includes(text))
42
+ parts.push(text);
43
+ current = current.cause;
44
+ }
45
+ return parts.length ? parts.join(": ") : String(e);
46
+ }
47
+ /** Rejects JSON a Python peer can't read back as sent. */
48
+ export function assertPortableJson(value, what) {
49
+ const problem = portabilityProblem(value);
50
+ if (problem !== undefined)
51
+ throw ApplicationFailure.create({
52
+ type: "NonPortableJson",
53
+ nonRetryable: true,
54
+ message: `${what} ${problem}`,
55
+ });
56
+ }
57
+ export function assertAutoModeHasEvaluator(policy, evaluator) {
58
+ if (evaluator !== undefined || !policy.auto_mode_enabled)
59
+ return;
60
+ throw ApplicationFailure.create({
61
+ type: "AutoModeWithoutEvaluator",
62
+ nonRetryable: true,
63
+ message: "ToolApprovalPolicy has auto_mode_enabled=True, but this agent has no autoModeEvaluator wired, so " +
64
+ "nothing could ever judge a call while the policy reported auto mode on. Either pass " +
65
+ "autoModeEvaluator (jevEvaluator() is the builtin), or use a policy with auto mode off.",
66
+ });
67
+ }
@@ -0,0 +1,88 @@
1
+ import type { z } from "zod";
2
+ import type { AgentMessage, AutoApprovalCriteria, AutoModeEvaluator, MessageContext, MidTurn, Schema, ToolApprovalPolicy } from "../agent-protocol/index.ts";
3
+ import type { StateDecl } from "../state/index.ts";
4
+ /** One `@agent.accepts`-style handler declaration: the static half, discoverable without a run. */
5
+ export interface HandlerDecl<I extends z.ZodType = z.ZodType, O extends z.ZodType = z.ZodType> {
6
+ readonly description: string;
7
+ readonly input: I;
8
+ readonly output: O;
9
+ readonly midTurn: MidTurn;
10
+ readonly modelCallable: boolean;
11
+ /** The input's parameter name (Python's handler parameter); a subagent send tool's argument. */
12
+ readonly inputName: string;
13
+ }
14
+ export type HandlerImpl<D extends HandlerDecl> = (message: z.output<D["input"]>, ctx: MessageContext) => Promise<z.input<D["output"]>>;
15
+ export interface Admission {
16
+ message: AgentMessage;
17
+ turn_id: string;
18
+ turn_number: number;
19
+ message_id: string;
20
+ /** Stream offset of the message's message_accepted; absent in runs carried before it was kept. */
21
+ accepted_offset?: number;
22
+ }
23
+ export interface ApprovalEntry {
24
+ tool_id: string;
25
+ tool_name: string;
26
+ tool_input: Record<string, unknown>;
27
+ turn_number: number;
28
+ turn_id: string;
29
+ message_id: string | null;
30
+ short_id: string;
31
+ inherently_safe: boolean;
32
+ status: "pending" | "approved" | "denied";
33
+ reason: string | null;
34
+ remember: boolean;
35
+ }
36
+ export interface CallbackEntry {
37
+ tool_id: string;
38
+ tool_name: string;
39
+ tool_input: Record<string, unknown>;
40
+ output_schema: Record<string, unknown>;
41
+ output: Schema;
42
+ turn_number: number;
43
+ turn_id: string;
44
+ message_id: string | null;
45
+ status: "pending" | "resolved";
46
+ outcome: "ok" | "error" | "timeout";
47
+ result: unknown;
48
+ error: string | null;
49
+ }
50
+ export interface SubagentInstance {
51
+ handle: string;
52
+ workflow_id: string;
53
+ agent_key: string;
54
+ last_consumed_offset: number;
55
+ next_ticket: number;
56
+ serving: number;
57
+ }
58
+ export interface RunnerOptions {
59
+ handlers: Readonly<Record<string, HandlerDecl>>;
60
+ approvalPolicyDefault: ToolApprovalPolicy;
61
+ autoApprovalCriteriaDefault?: AutoApprovalCriteria | undefined;
62
+ autoModeEvaluator?: AutoModeEvaluator | undefined;
63
+ states?: Readonly<Record<string, AnyStateDecl>> | undefined;
64
+ /** The agent's validated init data, handed to each state's `initial`. */
65
+ data?: unknown;
66
+ }
67
+ export type AnyStateDecl = StateDecl<z.ZodType<Record<string, unknown>>>;
68
+ export type ObjectSchema = Schema<Record<string, unknown>, Record<string, unknown>>;
69
+ /**
70
+ * A harness tool: the AI SDK tool shape (`description`, `inputSchema`, optional `outputSchema`,
71
+ * `execute`) plus where it runs and how it is gated. A tool with no `execute` is a callback tool,
72
+ * fulfilled by a client against its required `outputSchema`.
73
+ */
74
+ export interface HarnessTool<I = Record<string, unknown>, O = unknown> {
75
+ readonly kind: "inline" | "activity" | "callback";
76
+ readonly name: string;
77
+ readonly description: string;
78
+ readonly inputSchema: ObjectSchema;
79
+ readonly outputSchema: Schema | undefined;
80
+ readonly inherentlySafe: boolean;
81
+ readonly autoApprovalCriteria: string | null;
82
+ readonly injected: readonly string[];
83
+ /** The model-facing JSON schema of the arguments (injected parameters are not in it). */
84
+ readonly parameters: Record<string, unknown>;
85
+ /** Run the call. Only valid inside `runner.runTool(...)`. */
86
+ invoke(input: I): Promise<O>;
87
+ }
88
+ export type AnyHarnessTool = HarnessTool<never, unknown>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,79 @@
1
+ import { WorkflowStream } from "@temporalio/workflow-streams/workflow";
2
+ import { AutoApprovalCriteria, ToolApprovalPolicy, type AgentConfig, type AgentStatus, type AgentStreamItem, type Schema, type TurnStreamContext } from "./agent-protocol/index.ts";
3
+ import { StateRef } from "./state/index.ts";
4
+ import { CallbackToolError, ToolApprovalDenied, errorText } from "./agent-workflow/errors.ts";
5
+ import type { Admission, HandlerDecl, HandlerImpl, RunnerOptions, SubagentInstance } from "./agent-workflow/types.ts";
6
+ export { CallbackToolError, ToolApprovalDenied, errorText, };
7
+ export type { Admission, HandlerDecl, HandlerImpl, RunnerOptions, SubagentInstance, };
8
+ export interface ToolCall {
9
+ readonly runner: AgentWorkflowRunner;
10
+ readonly toolId: string;
11
+ readonly injections: Readonly<Record<string, unknown>>;
12
+ }
13
+ export declare const messageIdStore: ALS<T>;
14
+ export declare const toolCallStore: ALS<T>;
15
+ /** The in-flight tool call, or throw: tools must be invoked through `runner.runTool`. */
16
+ export declare function currentToolCall(what: string): ToolCall;
17
+ export declare const AMBIENT: unique symbol;
18
+ export declare class AgentWorkflowRunner {
19
+ #private;
20
+ readonly agentId: string;
21
+ readonly stream: WorkflowStream;
22
+ constructor(config: AgentConfig, options: RunnerOptions);
23
+ get closed(): boolean;
24
+ /** The live turn context, stamped with the ambient participant's message id; null when idle. */
25
+ get currentStreamContext(): TurnStreamContext | null;
26
+ get approvalPolicy(): ToolApprovalPolicy;
27
+ /** Install a new policy; pending calls it now allow-lists are approved in the same step. */
28
+ setApprovalPolicy(policy: ToolApprovalPolicy): void;
29
+ get autoApprovalCriteria(): AutoApprovalCriteria;
30
+ setAutoApprovalCriteria(criteria: AutoApprovalCriteria): void;
31
+ assignToolCriteria(toolName: string, criteriaSet: string): void;
32
+ get status(): AgentStatus;
33
+ /** Publish a payload on the current turn, attributed to the ambient message. */
34
+ publish(event: AgentStreamItem): void;
35
+ /**
36
+ * Run one tool call with its id and injections in scope; every harness tool needs this. A tool
37
+ * picked by a model at run time takes its (unvalidated) JSON arguments; the tool validates them.
38
+ */
39
+ runTool<I, O>(callId: string, tool: {
40
+ name?: string;
41
+ invoke(input: I): Promise<O>;
42
+ }, input: I, options?: {
43
+ injections?: Record<string, unknown>;
44
+ }): Promise<O>;
45
+ runTool<O>(callId: string, tool: {
46
+ name?: string;
47
+ invoke(input: never): Promise<O>;
48
+ }, input: unknown, options?: {
49
+ injections?: Record<string, unknown>;
50
+ }): Promise<O>;
51
+ /** Declared state: each snapshot was published at construction, then every committed mutation. */
52
+ readonly state: Readonly<Record<string, StateRef<Record<string, unknown>>>>;
53
+ run(impls: Readonly<Record<string, HandlerImpl<HandlerDecl>>>): Promise<void>;
54
+ /** @internal Enforce the approval policy for the in-flight tool call. Throws ToolApprovalDenied. */
55
+ applyApprovalPolicy(toolId: string, toolName: string, toolInput: Record<string, unknown>, opts: {
56
+ inherentlySafe: boolean;
57
+ description: string | null;
58
+ autoApprovalCriteria: string | null;
59
+ }): Promise<void>;
60
+ /** @internal The generic body of a callback tool: park until a client provides the result. */
61
+ awaitCallbackResult(args: {
62
+ toolId: string;
63
+ toolName: string;
64
+ toolInput: Record<string, unknown>;
65
+ output: Schema;
66
+ outputSchema: Record<string, unknown>;
67
+ timeout: string | number | undefined;
68
+ }): Promise<unknown>;
69
+ /** Start a child agent; returns its short, tree-unique handle (also its agent_id). */
70
+ startSubagent(agentKey: string, workflowType: string, taskQueue: string, { config, data }?: {
71
+ config?: Partial<AgentConfig>;
72
+ data?: unknown;
73
+ }): Promise<string>;
74
+ stopSubagent(handle: string): Promise<void>;
75
+ /** Send one message to a subagent and await its reply. Turns to one subagent run FIFO. */
76
+ runSubagentTurn(handle: string, msgType: string, payload: Record<string, unknown>): Promise<Record<string, unknown>>;
77
+ /** @internal Stamp the envelope and publish. `messageId` defaults to the ambient participant. */
78
+ pub(turnId: string, turnNumber: number, event: AgentStreamItem, messageId?: string | null | typeof AMBIENT): void;
79
+ }