bazis 0.98.34 → 0.99.1

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.
@@ -1,11 +1,12 @@
1
- import type { ServiceProvider } from "../di";
2
- import type { AgentRegistry } from "./AgentRegistry";
1
+ import { createToken, type ServiceProvider } from "../di";
2
+ import { modelValidatorAdapter } from "../../library/validation";
3
+ import type { AgentDataDefinition } from "./AgentDataDefinition";
4
+ import { AgentRegistry, type ToolDefinition } from "./AgentRegistry";
3
5
  import {
4
6
  AgentExecutionDriver,
5
7
  type AgentRuntimeInvokeOptions,
6
8
  type AgentRuntimeOptions,
7
9
  type AgentRuntimeResult,
8
- type AgentRuntimeTaskInvokeOptions,
9
10
  } from "./internal/AgentExecutionDriver";
10
11
  import type { AgentModelProvider } from "./ModelProvider";
11
12
 
@@ -14,34 +15,70 @@ export {
14
15
  type AgentRuntimeOptions,
15
16
  type AgentRuntimeResult,
16
17
  type AgentRuntimeStatus,
17
- type AgentRuntimeTaskInvokeOptions,
18
18
  type AgentRuntimeToolCallContext,
19
19
  type AgentRuntimeToolExecutionOptions,
20
20
  } from "./internal/AgentExecutionDriver";
21
21
 
22
- /** Public compatibility facade for the owner-private execution driver. */
22
+ /**
23
+ * Optional runtime settings (limits, approval policy, audit sink, context
24
+ * builder). Register a value in any module; the LLM connector reads it from
25
+ * the root container when it creates {@link AgentRuntime}.
26
+ */
27
+ export const AGENT_RUNTIME_OPTIONS = createToken<AgentRuntimeOptions>("AgentRuntimeOptions");
28
+
29
+ /**
30
+ * Runs meta-agents: an agent is data ({@link AgentDataDefinition}) — a name,
31
+ * instructions and the names of Tools it may call. The Tools themselves are
32
+ * code, registered in `@Module.tools`. Injected by type; `llmConnect` and
33
+ * `llmRouter` register it next to the model provider.
34
+ *
35
+ * ```ts
36
+ * const result = await this.agents.run(
37
+ * { name: "support", instructions: "Answer about orders.", toolNames: ["orders.find"] },
38
+ * { input: "Where is order 42?" },
39
+ * );
40
+ * ```
41
+ */
23
42
  export class AgentRuntime {
24
- private readonly driver: AgentExecutionDriver;
43
+ private readonly catalog: AgentRegistry;
44
+ private readonly options: AgentRuntimeOptions;
25
45
 
26
46
  constructor(
27
- services: ServiceProvider,
28
- registry: AgentRegistry,
29
- modelProvider: AgentModelProvider,
47
+ private readonly services: ServiceProvider,
48
+ private readonly modelProvider: AgentModelProvider,
30
49
  options: AgentRuntimeOptions = {},
31
50
  ) {
32
- this.driver = new AgentExecutionDriver(services, registry, modelProvider, options);
51
+ this.catalog = AgentRegistry.fromContainer(services);
52
+ this.options = {
53
+ ...options,
54
+ toolExecutorOptions: { schemaValidator: modelValidatorAdapter, ...options.toolExecutorOptions },
55
+ };
56
+ // Invalid options and hook setup fail here, at the first resolve, not on the first run.
57
+ new AgentExecutionDriver(services, this.catalog, modelProvider, this.options);
58
+ }
59
+
60
+ /** The Tools an agent definition may name in `toolNames`. */
61
+ listTools(): readonly ToolDefinition[] {
62
+ return this.catalog.listTools();
33
63
  }
34
64
 
35
- invoke(agentName: string, options: AgentRuntimeInvokeOptions = {}): Promise<AgentRuntimeResult> {
36
- return this.driver.invoke(agentName, options);
65
+ /**
66
+ * Checks a definition the way `run` does, without calling the model: an
67
+ * invalid field or a tool name not registered in `@Module.tools` throws
68
+ * AgentSetupError. Use it before saving a definition an operator edited.
69
+ */
70
+ check(definition: AgentDataDefinition): void {
71
+ AgentRegistry.fromDefinition(definition, this.catalog.listTools());
37
72
  }
38
73
 
39
- invokeTask(
40
- agentName: string,
41
- taskName: string,
42
- input: unknown,
43
- options: AgentRuntimeTaskInvokeOptions = {},
44
- ): Promise<AgentRuntimeResult> {
45
- return this.driver.invokeTask(agentName, taskName, input, options);
74
+ /**
75
+ * Runs one agent definition. An invalid definition, or a tool name that is
76
+ * not registered in `@Module.tools`, rejects with AgentSetupError before the
77
+ * model is called; failures of the run itself come back as `status: "failed"`.
78
+ */
79
+ async run(definition: AgentDataDefinition, options: AgentRuntimeInvokeOptions = {}): Promise<AgentRuntimeResult> {
80
+ const registry = AgentRegistry.fromDefinition(definition, this.catalog.listTools());
81
+ const driver = new AgentExecutionDriver(this.services, registry, this.modelProvider, this.options);
82
+ return driver.invoke(definition.name, options);
46
83
  }
47
84
  }
@@ -1232,15 +1232,15 @@ export class AgentToolExecutor {
1232
1232
  for (let index = 0; index < agent.tools.length; index += 1) {
1233
1233
  const visible = agent.tools[index] as ToolDefinition;
1234
1234
  if (visible.target === tool.target || visible.metadata.name === tool.metadata.name) {
1235
- return { allowed: true, agentName: agent.metadata.name };
1235
+ return { allowed: true, agentName: agent.name };
1236
1236
  }
1237
1237
  }
1238
1238
 
1239
1239
  return {
1240
1240
  allowed: false,
1241
- agentName: agent.metadata.name,
1241
+ agentName: agent.name,
1242
1242
  code: "TOOL_NOT_VISIBLE_TO_AGENT",
1243
- message: `Tool "${tool.metadata.name}" is not visible to agent "${agent.metadata.name}".`,
1243
+ message: `Tool "${tool.metadata.name}" is not visible to agent "${agent.name}".`,
1244
1244
  status: "denied",
1245
1245
  };
1246
1246
  }
@@ -1,228 +1,137 @@
1
1
  # bazis Agent
2
2
 
3
- `core/agent` is the first executable foundation for bazis AI. It contains
4
- provider-neutral metadata, discovery and DI-backed tool execution:
5
-
6
- - `@Agent`
7
- - `@Task`
8
- - `@Tool`
9
- - `@Prompt`
10
- - `collectAgentCatalog`
11
- - `AgentRegistry`
12
- - generated metadata via `bun run di:generate`
3
+ `core/agent` runs meta-agents. An agent is data — a name, instructions and
4
+ the names of the Tools it may call — so it can live in a database, be edited
5
+ by an operator and change without a deploy. Tools are code: classes with
6
+ `@Tool`, registered in `@Module.tools` and executed through bazis DI with
7
+ approval, audit, retries and deadlines.
8
+
9
+ - `@Tool` and `@Module.tools` — what agents may do
10
+ - `AgentRuntime` — runs an agent definition; injected by type
11
+ - `AGENT_RUNTIME_OPTIONS` — optional runtime settings
12
+ - `agentToolHooks` — enforcement, settlement and observer hooks around Tools
13
13
  - provider-neutral semantic model (`agentMessage`, `agentToolCall`,
14
- `agentModelRequest`, `agentModelResponse`)
15
- - prompt/context rendering via `DefaultAgentContextBuilder`
16
- - DI-backed `AgentToolExecutor`
14
+ `agentModelRequest`, `agentModelResponse`, `agentOutputContract`)
15
+ - context assembly via `DefaultAgentContextBuilder`
17
16
 
18
- Model providers live behind infra connectors. Long-term memory and streaming are
19
- still separate layers on top of this runtime boundary.
17
+ Model providers live behind infra connectors (`llmConnect`, `llmRouter`); they
18
+ also register `AgentRuntime`.
20
19
 
21
20
  ```ts
22
- import { Agent, Module, Task, Tool, agentOutput } from "bazis";
21
+ import { Module, Tool, scoped, type AgentToolExecutionContext } from "bazis";
23
22
 
24
- class CreateRequirementsRequest {
25
- feature!: string;
23
+ class FindOrderInput {
24
+ @Validator({ required: true, min: 1 }) id!: number;
26
25
  }
27
26
 
28
- class ProductRequirementsDocument {
29
- goal!: string;
30
- acceptanceCriteria!: string[];
31
- }
27
+ @Tool({ name: "orders.find", description: "Finds an order by id.", input: FindOrderInput, sideEffect: "read" })
28
+ export class FindOrderTool {
29
+ constructor(private readonly orders: IOrdersService) {}
32
30
 
33
- @Tool({
34
- name: "catalog.search",
35
- description: "Searches products in the catalog.",
36
- sideEffect: "read",
37
- })
38
- class SearchCatalogTool {}
39
-
40
- @Agent({
41
- name: "system-analyst",
42
- role: "System analyst",
43
- sections: [
44
- {
45
- kind: "developer",
46
- content: "Return concrete, testable requirements.",
47
- },
48
- {
49
- kind: "tool-policy",
50
- content: "Use read tools before proposing write actions.",
51
- },
52
- ],
53
- tools: [SearchCatalogTool],
54
- modelProfile: "reasoning",
55
- })
56
- class SystemAnalystAgent {
57
- @Task({
58
- name: "prepare-requirements",
59
- description: "Prepare a requirements document for a product feature.",
60
- })
61
- prepareRequirements(input: CreateRequirementsRequest): ProductRequirementsDocument {
62
- return agentOutput();
31
+ execute(input: FindOrderInput, context: AgentToolExecutionContext) {
32
+ return this.orders.find(input.id);
63
33
  }
64
34
  }
65
35
 
66
- @Module({
67
- agents: [SystemAnalystAgent],
68
- tools: [SearchCatalogTool],
69
- })
70
- class ProductModule {}
36
+ @Module({ tools: [FindOrderTool], providers: [scoped(OrdersService)] })
37
+ export class OrdersModule {}
71
38
  ```
72
39
 
73
- The DI core does not know about agent metadata. Importing `@/core/agent` or
74
- the root `bazis` API extends `@Module` with `agents`, `tools` and `prompts`.
75
- Each entry in `tools` creates one ordinary scoped provider owned by that module.
76
- An existing exact scoped self-class provider is reused; incompatible lifetimes,
77
- duplicates, and conflicting owners are rejected before activation.
78
- `AgentRegistry.fromContainer(container)` returns the immutable host Tool catalog
79
- from these registrations without constructing Tools. Metadata-defined agents
80
- select their own subset through `AgentRegistry.fromDefinition(definition, catalog.listTools())`.
81
- Internal contribution readers use an Agent-owned view of these optional fields.
82
- This also allows an isolated HTTP host to type-check when `generatedRuntime`
83
- references `AgentRegistry` only as a type, without loading the public Agent barrel
84
- and its DI augmentation. Runtime validation and provider ownership are unchanged.
85
- For simple cases, put role/instructions/sections directly on `@Agent`. Use a
86
- separate `@Prompt` class when the prompt is reused, versioned, or owned outside
87
- one agent.
88
-
89
- For startup-friendly discovery, `bun run di:generate` writes
90
- `src/generated/bazis/agentCatalog.ts`. Use
91
- `AgentRegistry.fromGeneratedModules([AppModule])` when the runtime should prefer
92
- the generated metadata index and still respect module ownership.
93
-
94
- The semantic model is the provider-neutral language for future runtime/provider
95
- adapters:
96
-
97
40
  ```ts
98
- const request = agentModelRequest({
99
- invocationId: "inv-1",
100
- messages: [agentMessage("user", "Prepare acceptance criteria")],
101
- tools: [agentToolContract({
102
- name: "catalog.search",
103
- description: "Searches products.",
104
- sideEffect: "read",
105
- })],
106
- });
41
+ import { AgentRuntime, type AgentDataDefinition } from "bazis/core/agent";
42
+
43
+ export class SupportService {
44
+ constructor(private readonly agents: AgentRuntime) {}
45
+
46
+ answer(question: string) {
47
+ const support: AgentDataDefinition = {
48
+ name: "support",
49
+ instructions: "Answer questions about orders. Use tools for data.",
50
+ toolNames: ["orders.find"],
51
+ modelProfile: "fast",
52
+ };
53
+ return this.agents.run(support, { input: question });
54
+ }
55
+ }
107
56
  ```
108
57
 
109
- Tool execution stays behind bazis DI, agent visibility and approval policy:
110
-
111
- ```ts
112
- import { modelValidatorAdapter } from "@/library/validation";
113
-
114
- const container = createContainer(AppModule);
115
- const registry = AgentRegistry.fromModules([AppModule]);
116
- const executor = new AgentToolExecutor(container, registry, {
117
- schemaValidator: modelValidatorAdapter,
118
- auditSink: (entry) => auditStore.write(entry),
119
- });
120
-
121
- const result = await executor.execute(agentToolCall({
122
- id: "call-1",
123
- name: "catalog.search",
124
- input: { query: "keyboard" },
125
- }), {
126
- agentName: "product-designer",
127
- });
128
- ```
58
+ `run` checks the definition before the model is called: a malformed field or a
59
+ tool name that is not registered in `@Module.tools` rejects with
60
+ `AgentSetupError` that lists the registered names. The model sees only the
61
+ Tools the definition names. `runtime.listTools()` returns the whole catalog,
62
+ for example for an agent editor, and `runtime.check(definition)` runs the same
63
+ check without the model — call it before saving a definition an operator edited.
129
64
 
130
- Audit entries redact `input`, `result` and execution `metadata` by default
131
- using `bazis/library/redaction` (`password`, `secret`, `token`, `apiKey`,
132
- `authorization`, `cookie`, etc.). Raw audit traces are an explicit local-debug
133
- escape hatch: pass `auditRedaction: false` on the executor or one execution.
65
+ The definition's `instructions` are the system message, sent as written.
66
+ `description` is for people and catalogs and is not sent to the model.
134
67
 
135
- Retries are opt-in. `write` and `external` tools require an idempotency key
136
- before the executor will repeat them:
68
+ Structured output is requested per run:
137
69
 
138
70
  ```ts
139
- await executor.execute(agentToolCall({
140
- id: "call-2",
141
- name: "catalog.reindex",
142
- }), {
143
- agentName: "product-designer",
144
- idempotencyKey: "catalog-reindex-1",
145
- retryPolicy: { maxAttempts: 3, delayMs: 100, backoff: "exponential" },
71
+ const result = await this.agents.run(analyst, {
72
+ input: { feature: "Checkout with a promo code" },
73
+ output: agentOutputContract({ mode: "json", schema: agentClassSchema("RequirementsDocument") }),
146
74
  });
75
+ result.output; // validated JSON
147
76
  ```
148
77
 
149
- Runtime-generated idempotency keys include both the invocation id and the
150
- unique model call id. Use `idempotencyKeyForCall` for a domain-specific stable
151
- key. Tool scopes have a bounded disposal wait (`scopeDisposeTimeoutMs`, five
152
- seconds by default). When execution settles after a timeout/abort, audit sinks
153
- receive a terminal `settlement` entry; an unknown write outcome stops runtime
154
- continuation.
78
+ A class schema comes from codegen (the class must be reachable for OpenAPI or
79
+ be a Tool contract); `agentJsonSchema(name, schema)` takes a JSON Schema
80
+ directly.
155
81
 
156
- Every tool call also has one 30-second deadline covering input validation,
157
- approval, audit, DI resolution, execution, output processing and result audit.
158
- Model provider calls default to 60 seconds. Set the corresponding `timeoutMs`
159
- to `0` only when an explicit compatibility opt-out is required.
160
-
161
- The first runtime slice invokes a model provider from infra, then routes tool
162
- calls through the executor:
82
+ Runtime settings — limits, approval policy, audit sink, context builder —
83
+ are registered once:
163
84
 
164
85
  ```ts
165
- const runtime = new AgentRuntime(
166
- container,
167
- AgentRegistry.fromModules([AppModule]),
168
- container.resolve(AGENT_MODEL_PROVIDER),
169
- );
170
-
171
- const result = await runtime.invoke("product-designer", {
172
- input: "Prepare acceptance criteria",
173
- maxSteps: 4,
174
- });
86
+ @Module({
87
+ providers: [DI.singleton(DI.valueProvider(AGENT_RUNTIME_OPTIONS, {
88
+ maxSteps: 6,
89
+ toolExecutorOptions: {
90
+ approvalPolicy: (request) => request.tool.sideEffect === "read",
91
+ auditSink: (entry) => auditStore.write(entry),
92
+ },
93
+ }))],
94
+ })
95
+ export class AgentSettingsModule {}
175
96
  ```
176
97
 
177
- For controller-style DX, prefer task methods on an agent. The task method is a
178
- business operation contract; the method body is not called by user code:
98
+ Tool input and output are validated by the model validator
99
+ (`modelValidatorAdapter`) unless `toolExecutorOptions.schemaValidator` says
100
+ otherwise. Audit entries redact `input`, `result` and execution `metadata`
101
+ by default using `bazis/library/redaction`.
179
102
 
180
- ```ts
181
- const result = await runtime.invokeTask("system-analyst", "prepare-requirements", {
182
- feature: "Checkout with a promo code",
183
- });
184
- ```
103
+ Retries are opt-in. `write` and `external` tools need an idempotency key before
104
+ the executor repeats them. Runtime-generated keys include both the invocation id
105
+ and the unique model call id; `toolExecution.idempotencyKeyForCall` gives a
106
+ domain-specific stable key. When execution settles after a timeout or abort,
107
+ audit sinks receive a terminal `settlement` entry; an unknown write outcome stops
108
+ the run.
185
109
 
186
- `@Task` can declare `input` and `output` explicitly. With `bun run di:generate`,
187
- simple method signatures are also read from code and written to generated
188
- metadata for faster startup-friendly discovery.
110
+ Every tool call has one 30-second deadline covering input validation, approval,
111
+ audit, DI resolution, execution, output processing and result audit. Model
112
+ provider calls default to 60 seconds. `timeoutMs: 0` disables either deadline.
189
113
 
190
- Prompt metadata is rendered into provider request context, not stored in the
191
- conversation history returned by the runtime:
114
+ Context limits keep long conversations within the model's window:
192
115
 
193
116
  ```ts
194
- const runtime = new AgentRuntime(container, registry, provider, {
195
- contextLimits: { maxMessages: 24, maxTokens: 8_000, maxChars: 32_000 },
196
- });
197
-
198
- const result = await runtime.invoke("product-designer", {
199
- input: "Prepare acceptance criteria",
117
+ await this.agents.run(support, {
118
+ messages: history,
200
119
  contextLimits: { maxMessages: 12, maxTokens: 4_000 },
201
120
  });
202
121
  ```
203
122
 
204
- `DefaultAgentContextBuilder` preserves the system prompt and newest conversation
205
- message when trimming old history. `maxTokens` uses a deterministic built-in
206
- estimator, and provider requests include `metadata.agentContext.trace` so context
207
- assembly is inspectable.
123
+ `DefaultAgentContextBuilder` preserves the system prompt and the newest
124
+ conversation message when trimming old history. Provider requests include
125
+ `metadata.agentContext.trace` so context assembly is inspectable.
208
126
 
209
- LLM clients are registered by infra connectors, not inside agent modules. Agents
210
- name a model profile; infra owns provider URLs, model ids, limits and fallback:
127
+ LLM clients are registered by infra connectors. Agents name a model profile;
128
+ infra owns provider URLs, model ids, limits and fallback:
211
129
 
212
130
  ```ts
213
131
  @Infra({
214
132
  llm: llmRouter({
215
- fast: llmProfile(llmConfig, openAiCompatibleAdapter(), {
216
- model: "gpt-4.1-mini",
217
- temperature: 0.1,
218
- maxOutputTokens: 1000,
219
- }),
220
- reasoning: llmProfile(llmConfig, openAiCompatibleAdapter(), {
221
- model: "gpt-4.1",
222
- temperature: 0.2,
223
- maxOutputTokens: 4000,
224
- fallback: "fast",
225
- }),
133
+ fast: llmProfile(llmConfig, openAiCompatibleAdapter(), { model: "gpt-4.1-mini" }),
134
+ reasoning: llmProfile(llmConfig, openAiCompatibleAdapter(), { model: "gpt-4.1", fallback: "fast" }),
226
135
  }, { defaultProfile: "fast" }),
227
136
  })
228
137
  class AppInfra {}
@@ -1,8 +1,5 @@
1
1
  import type { Class } from "../di";
2
2
 
3
- export { Agent } from "./decorators/Agent";
4
- export { Prompt } from "./decorators/Prompt";
5
- export { Task, type TaskDecoratorOptions } from "./decorators/Task";
6
3
  export { Tool } from "./decorators/Tool";
7
4
  export { describeTool } from "./Tool.contract";
8
5
  export type {
@@ -20,12 +17,12 @@ export {
20
17
  AgentToolPreCommitError,
21
18
  } from "./errors";
22
19
  export {
20
+ AGENT_RUNTIME_OPTIONS,
23
21
  AgentRuntime,
24
22
  type AgentRuntimeInvokeOptions,
25
23
  type AgentRuntimeOptions,
26
24
  type AgentRuntimeResult,
27
25
  type AgentRuntimeStatus,
28
- type AgentRuntimeTaskInvokeOptions,
29
26
  type AgentRuntimeToolCallContext,
30
27
  type AgentRuntimeToolExecutionOptions,
31
28
  } from "./AgentRuntime";
@@ -43,7 +40,6 @@ export {
43
40
  type DefaultAgentContextBuilderOptions,
44
41
  } from "./AgentContextBuilder";
45
42
  export {
46
- AgentToolExecutor,
47
43
  type AgentExecutableTool,
48
44
  type AgentToolAuditEntry,
49
45
  type AgentToolAuditFailureMode,
@@ -73,32 +69,10 @@ export {
73
69
  type AgentModelProvider,
74
70
  type AgentModelProviderContext,
75
71
  } from "./ModelProvider";
76
- export {
77
- AgentRegistry,
78
- collectAgentCatalog,
79
- type AgentCatalog,
80
- type AgentCatalogExtras,
81
- type AgentDefinition,
82
- type AgentMetadataIndex,
83
- type AgentTaskDefinition,
84
- type PromptDefinition,
85
- type ToolDefinition,
86
- } from "./AgentRegistry";
72
+ export type { ToolDefinition } from "./AgentRegistry";
87
73
  export type { AgentDataDefinition } from "./AgentDataDefinition";
88
74
  export {
89
- agentMetadataOf,
90
- agentTaskMetadataOf,
91
- promptMetadataOf,
92
75
  toolMetadataOf,
93
- type AgentMetadata,
94
- type AgentOptions,
95
- type AgentTaskMetadata,
96
- type AgentTaskOptions,
97
- type PromptMetadata,
98
- type PromptOptions,
99
- type PromptSectionKind,
100
- type PromptSectionMetadata,
101
- type PromptSectionOptions,
102
76
  type ToolApproval,
103
77
  type ToolMetadata,
104
78
  type ToolOptions,
@@ -115,7 +89,6 @@ export {
115
89
  agentModelCapabilities,
116
90
  agentModelRequest,
117
91
  agentModelResponse,
118
- agentOutput,
119
92
  agentOutputContract,
120
93
  agentText,
121
94
  agentToolCall,
@@ -162,9 +135,8 @@ export {
162
135
  // depend on program file order and silently stop merging in some projects.
163
136
  declare module "../di/module/types/BazisModule" {
164
137
  interface BazisModuleMetadata {
165
- readonly agents?: readonly Class<object>[];
138
+ /** Tools agents may call: classes with `@Tool`. An agent definition names them in `toolNames`. */
166
139
  readonly tools?: readonly Class<object>[];
167
- readonly prompts?: readonly Class<object>[];
168
140
  readonly agentToolHooks?: readonly import("./AgentToolHooks").AgentToolHookRegistrationV1[];
169
141
  }
170
142
  }