@jterrazz/intelligence 1.3.0 → 1.4.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.
package/README.md CHANGED
@@ -5,16 +5,17 @@
5
5
  [![NPM Version](https://img.shields.io/npm/v/@jterrazz/intelligence.svg)](https://www.npmjs.com/package/@jterrazz/intelligence)
6
6
  [![License](https://img.shields.io/npm/l/@jterrazz/intelligence.svg)](./LICENSE)
7
7
 
8
- `@jterrazz/intelligence` provides a clean, structured, and extensible foundation for building sophisticated AI agents. By combining a composable prompt system, safe tool integration, and a ports-and-adapters architecture, it empowers developers to create reliable and maintainable AI-powered applications.
8
+ `@jterrazz/intelligence` provides a clean, structured, and extensible foundation for building sophisticated AI agents. It's designed to help you create reliable and maintainable AI-powered applications by focusing on composability and type safety.
9
9
 
10
10
  ---
11
11
 
12
- ## Why Use This Library?
12
+ ## Core Principles
13
13
 
14
- - **🤖 Build Predictable Agents**: Use the composable prompt library to ensure your agents have a consistent personality, tone, and behavior.
15
- - **🛠️ Integrate Tools Safely**: `SafeToolAdapter` provides built-in error handling, logging, and Zod-based schema validation for all your tools.
16
- - **🏗️ Stay Flexible**: The ports-and-adapters architecture makes it easy to swap out underlying models or frameworks (like LangChain) without rewriting your core logic.
17
- - **🎯 Get Type-Safe Responses**: Move beyond string parsing with `AIResponseParser`, which validates and types your model's output against a Zod schema.
14
+ - **Composable Prompts**: Instead of monolithic prompts, the library offers a collection of constants. Mix and match them to build a precise system prompt that defines your agent's behavior, personality, and output format.
15
+
16
+ - **Safe, Typed Tools**: A `SafeToolAdapter` provides built-in error handling and Zod-based schema validation for any tool you create. This ensures that tool inputs are valid and that your agent can gracefully handle execution errors.
17
+
18
+ - **Ports & Adapters Architecture**: The library uses a hexagonal architecture to separate core logic from implementation details. This makes it easy to swap out underlying models or services (e.g., switching from OpenAI to Anthropic) without rewriting your application.
18
19
 
19
20
  ## Installation
20
21
 
@@ -26,7 +27,7 @@ npm install @jterrazz/intelligence
26
27
 
27
28
  ## Quick Start
28
29
 
29
- Get your first agent running in under a minute. This example uses a preset to create a helpful Discord community animator.
30
+ Get your first agent running in minutes. This example creates a helpful agent for a Discord community.
30
31
 
31
32
  ```typescript
32
33
  import {
@@ -55,277 +56,153 @@ console.log(response);
55
56
  // Output might be: "Hello, community! I'm here to help with any questions and keep the good vibes flowing. What's on your mind today?"
56
57
  ```
57
58
 
58
- ---
59
-
60
- ## Core Concepts
61
-
62
- ### 1. Composable Prompts
63
-
64
- Instead of writing monolithic prompts, the library provides a collection of composable string constants. Mix and match them to build a precise, fine-grained system prompt that defines your agent's behavior.
59
+ ## Creating Domain-Specific Agents
65
60
 
66
- - **`FOUNDATIONS`**: Core, non-negotiable rules (e.g., `PROMPT_LIBRARY.FOUNDATIONS.ETHICAL_CONDUCT`).
67
- - **`PERSONAS`**: The agent's identity and purpose (e.g., `PROMPT_LIBRARY.PERSONAS.EXPERT_ADVISOR`).
68
- - **`DOMAINS`**: The agent's area of expertise (e.g., `PROMPT_LIBRARY.DOMAINS.SOFTWARE_ENGINEERING`).
69
- - **`TONES`**: The emotional flavor of communication (e.g., `PROMPT_LIBRARY.TONES.PROFESSIONAL`).
70
- - **`FORMATS`**: The structural format of the output (e.g., `PROMPT_LIBRARY.FORMATS.JSON`).
71
- - **`LANGUAGES`**: The natural language for the response (e.g., `PROMPT_LIBRARY.LANGUAGES.ENGLISH_NATIVE`).
72
- - **`VERBOSITY`**: The level of detail in the response (e.g., `PROMPT_LIBRARY.VERBOSITY.DETAILED`).
73
- - **`RESPONSES`**: The strategic approach to responding (e.g., `PROMPT_LIBRARY.RESPONSES.ALWAYS_ENGAGE`).
61
+ The most powerful feature of `@jterrazz/intelligence` is its ability to create specialized, reusable agents. By extending the base adapters, you can encapsulate an agent's logic, prompts, and tools into a clean, type-safe class.
74
62
 
75
- This approach makes agent behavior more predictable and easier to modify.
63
+ ### 1. Data Extraction Agent (`BasicAgentAdapter`)
76
64
 
77
- ### 2. Safe Tool Integration
78
-
79
- The `SafeToolAdapter` is a wrapper for your functions that ensures they are executed safely.
80
-
81
- ```typescript
82
- import { SafeToolAdapter } from '@jterrazz/intelligence';
83
- import { z } from 'zod/v4';
84
-
85
- const weatherTool = new SafeToolAdapter(
86
- {
87
- name: 'get_weather',
88
- description: 'Get the current weather for a specific city.',
89
- execute: async ({ city }) => `The weather in ${city} is currently sunny.`,
90
- },
91
- {
92
- // Zod schema for automatic validation and type-safety
93
- schema: z.object({
94
- city: z.string().describe('The city name'),
95
- }),
96
- },
97
- );
98
- ```
99
-
100
- The adapter handles errors gracefully and integrates seamlessly with the agent, which will automatically provide the Zod schema to the underlying model.
101
-
102
- ### 3. Ports and Adapters Architecture
103
-
104
- The library is built on a hexagonal architecture.
105
-
106
- - **Ports (`/ports`)**: Define the contracts (interfaces) for core components like `Agent`, `Model`, and `Tool`.
107
- - **Adapters (`/adapters`)**: Provide concrete implementations. For example, `AutonomousAgentAdapter` is an adapter that uses LangChain, and `OpenRouterAdapter` is an adapter for the OpenRouter API.
108
-
109
- This separation of concerns means you can easily create your own adapters to support different models or services without changing the application's core logic.
110
-
111
- ```
112
- src/
113
- ├── ports/ # Abstract interfaces (the "what")
114
- └── adapters/ # Concrete implementations (the "how")
115
- ```
116
-
117
- ---
118
-
119
- ## Recipes
120
-
121
- ### Recipe: Code Review Assistant
122
-
123
- This recipe creates an agent that acts as an expert software engineer, providing detailed feedback on code.
124
-
125
- ```typescript
126
- import {
127
- AutonomousAgentAdapter,
128
- OpenRouterAdapter,
129
- SystemPromptAdapter,
130
- UserPromptAdapter,
131
- PROMPT_LIBRARY,
132
- } from '@jterrazz/intelligence';
133
-
134
- const model = new OpenRouterAdapter({
135
- apiKey: process.env.OPENROUTER_API_KEY!,
136
- modelName: 'anthropic/claude-3.5-sonnet',
137
- });
138
-
139
- // 1. Compose the system prompt from multiple parts (using rest arguments)
140
- const systemPrompt = new SystemPromptAdapter(
141
- PROMPT_LIBRARY.PERSONAS.EXPERT_ADVISOR,
142
- PROMPT_LIBRARY.DOMAINS.SOFTWARE_ENGINEERING,
143
- PROMPT_LIBRARY.TONES.PROFESSIONAL,
144
- PROMPT_LIBRARY.VERBOSITY.DETAILED,
145
- PROMPT_LIBRARY.FORMATS.MARKDOWN,
146
- PROMPT_LIBRARY.FOUNDATIONS.FACTUAL_ACCURACY,
147
- );
148
-
149
- // 2. Create the user request (using a single array)
150
- const userPrompt = new UserPromptAdapter([
151
- 'Please review this TypeScript code for best practices:',
152
- 'const x = (s) => s.trim();',
153
- ]);
154
-
155
- // 3. Configure and run the agent
156
- const agent = new AutonomousAgentAdapter('code-reviewer', {
157
- model,
158
- systemPrompt,
159
- });
160
-
161
- const response = await agent.run(userPrompt);
162
-
163
- console.log(response);
164
- ```
165
-
166
- ### Recipe: Simple Text Processor (BasicAgent)
167
-
168
- This example shows how to use the simpler `BasicAgentAdapter` for one-shot responses without tools.
169
-
170
- ```typescript
171
- import {
172
- BasicAgentAdapter,
173
- OpenRouterAdapter,
174
- SystemPromptAdapter,
175
- UserPromptAdapter,
176
- PROMPT_LIBRARY,
177
- } from '@jterrazz/intelligence';
178
-
179
- const model = new OpenRouterAdapter({
180
- apiKey: process.env.OPENROUTER_API_KEY!,
181
- modelName: 'anthropic/claude-3.5-sonnet',
182
- });
183
-
184
- // 1. Create a simple system prompt for text processing
185
- const systemPrompt = new SystemPromptAdapter(
186
- PROMPT_LIBRARY.PERSONAS.EXPERT_ADVISOR,
187
- PROMPT_LIBRARY.TONES.PROFESSIONAL,
188
- PROMPT_LIBRARY.FORMATS.MARKDOWN,
189
- 'You are a helpful assistant that improves text clarity and grammar.',
190
- );
191
-
192
- // 2. Create a basic agent (no tools needed)
193
- const agent = new BasicAgentAdapter('text-processor', {
194
- model,
195
- systemPrompt,
196
- });
197
-
198
- // 3. Run a simple query
199
- const userPrompt = new UserPromptAdapter(
200
- 'Please improve this text: "Me and john was going to store yesterday"',
201
- );
202
- const response = await agent.run(userPrompt);
203
-
204
- console.log(response);
205
- // Expected output: A grammatically corrected and improved version of the text
206
- ```
207
-
208
- ### Recipe: Structured Data Extraction (BasicAgent with Schema)
209
-
210
- This example shows how to use `BasicAgentAdapter` with schema parsing for structured responses.
65
+ Use `BasicAgentAdapter` for simpler, one-shot tasks where you need a structured response but don't require complex tool use. This example creates a reusable agent to extract contact information.
211
66
 
212
67
  ```typescript
213
68
  import {
214
69
  BasicAgentAdapter,
70
+ ModelPort,
215
71
  OpenRouterAdapter,
216
72
  SystemPromptAdapter,
217
73
  UserPromptAdapter,
218
74
  PROMPT_LIBRARY,
219
75
  } from '@jterrazz/intelligence';
220
- import { z } from 'zod/v4';
221
-
76
+ import { z } from 'zod';
77
+
78
+ // 1. Define the output type for compile-time type-safety
79
+ interface Contact {
80
+ name: string;
81
+ email: string;
82
+ }
83
+
84
+ // 2. Create a specialized agent by extending BasicAgentAdapter
85
+ class ContactExtractorAgent extends BasicAgentAdapter<Contact> {
86
+ constructor(model: ModelPort) {
87
+ super('contact-extractor', {
88
+ model,
89
+ // Define the schema for runtime validation and type inference
90
+ schema: z.object({
91
+ name: z.string().describe('The full name of the person'),
92
+ email: z.string().email().describe('The email address'),
93
+ }),
94
+ // Compose the system prompt from the library
95
+ systemPrompt: new SystemPromptAdapter(
96
+ PROMPT_LIBRARY.FORMATS.JSON,
97
+ 'You are an expert at extracting contact details from text.',
98
+ ),
99
+ });
100
+ }
101
+ }
102
+
103
+ // 3. Instantiate and use the agent
222
104
  const model = new OpenRouterAdapter({
223
105
  apiKey: process.env.OPENROUTER_API_KEY!,
224
106
  modelName: 'anthropic/claude-3.5-sonnet',
225
107
  });
108
+ const agent = new ContactExtractorAgent(model);
226
109
 
227
- // 1. Define the response schema
228
- const extractionSchema = z.object({
229
- name: z.string(),
230
- email: z.string().email(),
231
- phone: z.string().optional(),
232
- company: z.string().optional(),
233
- });
234
-
235
- // 2. Create a system prompt for data extraction
236
- const systemPrompt = new SystemPromptAdapter(
237
- PROMPT_LIBRARY.PERSONAS.EXPERT_ADVISOR,
238
- PROMPT_LIBRARY.TONES.PROFESSIONAL,
239
- PROMPT_LIBRARY.FORMATS.JSON,
240
- 'You extract contact information from text and return it as JSON.',
241
- );
242
-
243
- // 3. Create a basic agent with schema parsing
244
- const agent = new BasicAgentAdapter('contact-extractor', {
245
- model,
246
- schema: extractionSchema,
247
- systemPrompt,
248
- });
110
+ const text = 'Say hi to John Doe, you can reach him at john.doe@example.com.';
111
+ const contact = await agent.run(new UserPromptAdapter(text));
249
112
 
250
- // 4. Run the query
251
- const userPrompt = new UserPromptAdapter(
252
- 'Extract contact info: "Hi, I\'m John Doe from TechCorp. Email me at john@techcorp.com or call 555-1234"',
253
- );
254
- const response = await agent.run(userPrompt);
255
-
256
- // 5. Get both raw response and parsed data
257
- console.log('Raw response:', response);
258
- const parsedData = agent.getLastParsedResult();
259
- console.log('Parsed data:', parsedData);
260
- // Expected: { name: "John Doe", email: "john@techcorp.com", phone: "555-1234", company: "TechCorp" }
113
+ console.log(contact);
114
+ // Output: { name: 'John Doe', email: 'john.doe@example.com' }
261
115
  ```
262
116
 
263
- ### Recipe: Weather Bot with Tools
117
+ ### 2. Autonomous Agent with a Custom Tool (`AutonomousAgentAdapter`)
264
118
 
265
- This example shows how to give an agent a tool and have it respond to a user query.
119
+ Use `AutonomousAgentAdapter` when you need an agent that can reason and use tools to accomplish a task. This example creates a weather assistant that uses a tool and returns a structured JSON response.
266
120
 
267
121
  ```typescript
268
122
  import {
269
123
  AutonomousAgentAdapter,
124
+ ModelPort,
270
125
  OpenRouterAdapter,
271
126
  SafeToolAdapter,
272
127
  SystemPromptAdapter,
273
128
  UserPromptAdapter,
274
- PROMPT_LIBRARY,
275
129
  } from '@jterrazz/intelligence';
276
- import { z } from 'zod/v4';
277
-
278
- // Assume 'model' is already configured
279
-
280
- // 1. Define the tool
281
- const weatherTool = new SafeToolAdapter(
282
- {
283
- name: 'get_weather',
284
- description: 'Get the current weather for a location.',
285
- execute: async ({ city }) => {
286
- // In a real app, you would fetch from a weather API here
287
- return `The weather in ${city} is 75°F and sunny.`;
288
- },
130
+ import { z } from 'zod';
131
+
132
+ // 1. Define the agent's final output type
133
+ interface WeatherReport {
134
+ city: string;
135
+ temperature: number;
136
+ conditions: string;
137
+ forecast: string;
138
+ }
139
+
140
+ // 2. Define a tool. Its `execute` function should return a string,
141
+ // as the agent will process this output to formulate a final answer.
142
+ const weatherTool = new SafeToolAdapter({
143
+ name: 'get_weather',
144
+ description: 'Gets the current weather for a specified city.',
145
+ schema: z.object({ city: z.string().describe('The name of the city') }),
146
+ execute: async ({ city }) => {
147
+ // In a real app, you would call a weather API here.
148
+ // The tool returns raw data, often as a JSON string.
149
+ if (city.toLowerCase() === 'paris') {
150
+ return JSON.stringify({
151
+ city: 'Paris',
152
+ temperature: 25,
153
+ conditions: 'sunny',
154
+ forecast: 'clear skies for the next 24 hours',
155
+ });
156
+ }
157
+ return `Sorry, I don't have weather information for ${city}.`;
289
158
  },
290
- { schema: z.object({ city: z.string().describe('City name') }) },
291
- );
159
+ });
292
160
 
293
- // 2. Create an agent that knows how to use tools
294
- const agent = new AutonomousAgentAdapter('weather-bot', {
295
- model,
296
- systemPrompt: new SystemPromptAdapter(PROMPT_LIBRARY.PRESETS.EMPATHETIC_SUPPORT_AGENT), // A good general-purpose preset
297
- tools: [weatherTool], // Pass the tool instance directly
161
+ // 3. Create a specialized agent that uses the tool and has a structured output
162
+ class WeatherAssistantAgent extends AutonomousAgentAdapter<WeatherReport> {
163
+ constructor(model: ModelPort) {
164
+ super('weather-assistant', {
165
+ model,
166
+ tools: [weatherTool],
167
+ // This schema defines the agent's FINAL output structure
168
+ schema: z.object({
169
+ city: z.string(),
170
+ temperature: z.number(),
171
+ conditions: z.string(),
172
+ forecast: z.string(),
173
+ }),
174
+ systemPrompt: new SystemPromptAdapter(
175
+ 'You are a helpful weather assistant.',
176
+ 'You must use the provided tools to get weather information and then respond with a structured JSON object.',
177
+ ),
178
+ });
179
+ }
180
+ }
181
+
182
+ // 4. Instantiate and use the agent
183
+ const model = new OpenRouterAdapter({
184
+ apiKey: process.env.OPENROUTER_API_KEY!,
185
+ modelName: 'anthropic/claude-3.5-sonnet',
298
186
  });
187
+ const agent = new WeatherAssistantAgent(model);
299
188
 
300
- // 3. Run the agent with a user query that requires the tool
301
- const response = await agent.run(new UserPromptAdapter("What's the weather like in Boston?"));
189
+ const response = await agent.run(new UserPromptAdapter("What's the weather like in Paris?"));
302
190
 
303
191
  console.log(response);
304
- // Expected output: "The weather in Boston is 75°F and sunny."
192
+ // Output: { city: 'Paris', temperature: 25, conditions: 'sunny', forecast: 'clear skies for the next 24 hours' }
305
193
  ```
306
194
 
307
- ---
308
-
309
- ## API Reference
310
-
311
- ### Core Components
195
+ ## Development
312
196
 
313
- | Class | Description |
314
- | ------------------------ | ------------------------------------------------------------------------------- |
315
- | `AutonomousAgentAdapter` | The main agent implementation. Runs prompts and coordinates tools autonomously. |
316
- | `BasicAgentAdapter` | A basic agent for one-shot responses without tools or complex logic. |
317
- | `OpenRouterModelAdapter` | An adapter for connecting to any model on the OpenRouter platform. |
318
- | `SafeToolAdapter` | A type-safe wrapper for creating tools with validation and error handling. |
319
- | `SystemPromptAdapter` | A simple adapter to generate a system prompt string from a prompt array. |
320
- | `UserPromptAdapter` | A simple adapter to generate a user prompt string from a prompt array. |
321
- | `AIResponseParser` | A utility to parse a model's string output into a typed object using Zod. |
322
- | `PROMPT_LIBRARY` | A frozen object containing the entire composable prompt library. |
197
+ - **Linting**: `npm run lint`
198
+ - **Testing**: `npm run test`
323
199
 
324
200
  ## Contributing
325
201
 
326
- Contributions are welcome! Please feel free to submit a Pull Request.
202
+ Contributions are welcome! Please feel free to open an issue or submit a pull request.
203
+
204
+ ---
327
205
 
328
- ## Author
206
+ ## License
329
207
 
330
- - Jean-Baptiste Terrazzoni ([@jterrazz](https://github.com/jterrazz))
331
- - Email: contact@jterrazz.com
208
+ This project is licensed under the [MIT License](./LICENSE).
@@ -1,14 +1,14 @@
1
1
  import { type LoggerPort } from '@jterrazz/logger';
2
- import { type z } from 'zod/v4';
2
+ import { z } from 'zod/v4';
3
3
  import { type AgentPort } from '../../ports/agent.port.js';
4
4
  import type { ModelPort } from '../../ports/model.port.js';
5
5
  import type { PromptPort } from '../../ports/prompt.port.js';
6
6
  import type { ToolPort } from '../../ports/tool.port.js';
7
7
  import type { SystemPromptAdapter } from '../prompts/system-prompt.adapter.js';
8
- export interface AutonomousAgentOptions<T = unknown> {
8
+ export interface AutonomousAgentOptions<TOutput = string> {
9
9
  logger?: LoggerPort;
10
10
  model: ModelPort;
11
- schema?: z.ZodSchema<T>;
11
+ schema?: z.ZodSchema<TOutput>;
12
12
  systemPrompt: SystemPromptAdapter;
13
13
  tools: ToolPort[];
14
14
  verbose?: boolean;
@@ -16,12 +16,13 @@ export interface AutonomousAgentOptions<T = unknown> {
16
16
  /**
17
17
  * An autonomous agent that uses tools and a structured prompt to accomplish tasks.
18
18
  * It can decide whether to respond or remain silent and supports schema-validated responses.
19
+ * @template TOutput - The TypeScript type of the output
19
20
  */
20
- export declare class AutonomousAgentAdapter<T = unknown> implements AgentPort {
21
+ export declare class AutonomousAgentAdapter<TOutput = string> implements AgentPort<PromptPort, TOutput> {
21
22
  readonly name: string;
22
23
  private readonly options;
23
- constructor(name: string, options: AutonomousAgentOptions<T>);
24
- run(userPrompt?: PromptPort): Promise<null | string>;
24
+ constructor(name: string, options: AutonomousAgentOptions<TOutput>);
25
+ run(input?: PromptPort): Promise<null | TOutput>;
25
26
  private createExecutor;
26
27
  private parseAgentOutput;
27
28
  private resolveUserInput;
@@ -159,11 +159,13 @@ function _ts_generator(thisArg, body) {
159
159
  }
160
160
  import { ChatPromptTemplate } from '@langchain/core/prompts';
161
161
  import { AgentExecutor, createStructuredChatAgent } from 'langchain/agents';
162
+ import { z } from 'zod/v4';
162
163
  import { AIResponseParser } from '../utils/ai-response-parser.js';
163
- var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<OUTPUT_FORMAT>\nCRITICAL: The format instructions in this section are the ONLY valid way to structure your response. Your entire response MUST be a single JSON markdown code block. Any formatting guidelines within the <OBJECTIVE> section apply ONLY to the content inside the "RESPOND:" part of your final "action_input".\n\nREQUIRED: You have two ways to respond:\n\n1. **Call a tool** to gather information. For this, you MUST output a JSON blob with the tool\'s name and its input.\n *Valid tool names are: {tool_names}*\n ```json\n {{\n "action": "tool_name_to_use",\n "action_input": "the input for the tool, or an empty object {{}} if no input is needed"\n }}\n ```\n\n2. **Provide the Final Answer** once you have enough information. For this, you MUST output a JSON blob with the "Final Answer" action.\n The "action_input" for a "Final Answer" MUST be a string that begins with either "RESPOND: " for a message or "SILENT: " for no message. This prefix is a literal part of the output string and MUST NOT be omitted.\n - To send a message:\n ```json\n {{\n "action": "Final Answer",\n "action_input": "RESPOND: <your response message>"\n }}\n ```\n - To stay silent:\n ```json\n {{\n "action": "Final Answer",\n "action_input": "SILENT: <your reason for staying silent>"\n }}\n ```\n\n YOU MUST ALWAYS INCLUDE "RESPOND:" OR "SILENT:" IN YOUR FINAL ANSWER\'S "action_input". FAILURE TO DO SO WILL CAUSE AN ERROR.\n</OUTPUT_FORMAT>\n\n<EXECUTION_CONTEXT>\nThis is internal data for your reference.\n\n<TOOLS>\n{tools}\n</TOOLS>\n\n<WORKING_MEMORY>\nThis is your internal thought process and previous tool usage.\n{agent_scratchpad}\n</WORKING_MEMORY>\n</EXECUTION_CONTEXT>\n';
164
+ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<GLOBAL_WRAPPER_OUTPUT_FORMAT>\nCRITICAL: The format instructions in this section are the ONLY valid way to structure your response. Your entire response MUST be a single JSON markdown code block. Any formatting guidelines within the <OBJECTIVE> section apply ONLY to the content inside the "RESPOND:" part of your final "action_input".\n\nREQUIRED: You have two ways to respond:\n\n1. **Call a tool** to gather information. For this, you MUST output a JSON blob with the tool\'s name and its input.\n *Valid tool names are: {tool_names}*\n ```json\n {{\n "action": "tool_name_to_use",\n "action_input": "the input for the tool, or an empty object {{}} if no input is needed"\n }}\n ```\n\n2. **Provide the Final Answer** once you have enough information. For this, you MUST output a JSON blob with the "Final Answer" action.\n The "action_input" for a "Final Answer" MUST be a string that begins with either "RESPOND: " for a message or "SILENT: " for no message. This prefix is a literal part of the output string and MUST NOT be omitted.\n - To send a message:\n ```json\n {{\n "action": "Final Answer",\n "action_input": "RESPOND: <your response message>"\n }}\n ```\n - To stay silent:\n ```json\n {{\n "action": "Final Answer",\n "action_input": "SILENT: <your reason for staying silent>"\n }}\n ```\n\n YOU MUST ALWAYS INCLUDE "RESPOND:" OR "SILENT:" IN YOUR FINAL ANSWER\'S "action_input". FAILURE TO DO SO WILL CAUSE AN ERROR.\n\n{schema_format}\n</OUTPUT_FORMAT>\n\n<EXECUTION_CONTEXT>\nThis is internal data for your reference.\n\n<TOOLS>\n{tools}\n</TOOLS>\n\n<WORKING_MEMORY>\nThis is your internal thought process and previous tool usage.\n{agent_scratchpad}\n</WORKING_MEMORY>\n</EXECUTION_CONTEXT>\n';
164
165
  /**
165
166
  * An autonomous agent that uses tools and a structured prompt to accomplish tasks.
166
167
  * It can decide whether to respond or remain silent and supports schema-validated responses.
168
+ * @template TOutput - The TypeScript type of the output
167
169
  */ export var AutonomousAgentAdapter = /*#__PURE__*/ function() {
168
170
  "use strict";
169
171
  function AutonomousAgentAdapter(name, options) {
@@ -176,9 +178,9 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
176
178
  _create_class(AutonomousAgentAdapter, [
177
179
  {
178
180
  key: "run",
179
- value: function run(userPrompt) {
181
+ value: function run(input) {
180
182
  return _async_to_generator(function() {
181
- var _this_options_logger, _this_options_logger1, executor, userInput, result, agentResponse, _this_options_logger2, _agentResponse_message, message, _this_options_logger3, _this_options_logger4, error, _this_options_logger5;
183
+ var _this_options_logger, _this_options_logger1, executor, userInput, result, agentResponse, _this_options_logger2, _agentResponse_message, message, _this_options_logger3, validatedResponse, _this_options_logger4, error, _this_options_logger5;
182
184
  return _ts_generator(this, function(_state) {
183
185
  switch(_state.label){
184
186
  case 0:
@@ -197,7 +199,7 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
197
199
  ];
198
200
  case 2:
199
201
  executor = _state.sent();
200
- userInput = this.resolveUserInput(userPrompt);
202
+ userInput = this.resolveUserInput(input);
201
203
  return [
202
204
  4,
203
205
  executor.invoke({
@@ -232,15 +234,24 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
232
234
  message = (_agentResponse_message = agentResponse.message) !== null && _agentResponse_message !== void 0 ? _agentResponse_message : '';
233
235
  if (this.options.schema) {
234
236
  ;
235
- this.validateResponseContent(message, this.options.schema);
237
+ validatedResponse = this.validateResponseContent(message, this.options.schema);
236
238
  (_this_options_logger3 = this.options.logger) === null || _this_options_logger3 === void 0 ? void 0 : _this_options_logger3.info("[".concat(this.name, "] Execution finished; response content validated."));
239
+ return [
240
+ 2,
241
+ validatedResponse
242
+ ];
237
243
  } else {
238
244
  ;
239
245
  (_this_options_logger4 = this.options.logger) === null || _this_options_logger4 === void 0 ? void 0 : _this_options_logger4.info("[".concat(this.name, "] Execution finished."));
246
+ // When no schema is provided, we assume TOutput is string (default), so message is the result
247
+ return [
248
+ 2,
249
+ message
250
+ ];
240
251
  }
241
252
  return [
242
- 2,
243
- message
253
+ 3,
254
+ 5
244
255
  ];
245
256
  case 4:
246
257
  error = _state.sent();
@@ -264,7 +275,7 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
264
275
  key: "createExecutor",
265
276
  value: function createExecutor() {
266
277
  return _async_to_generator(function() {
267
- var model, tools, prompt, agent;
278
+ var model, tools, schemaFormatInstructions, jsonSchema, isPrimitiveType, jsonSchemaString, prompt, agent;
268
279
  return _ts_generator(this, function(_state) {
269
280
  switch(_state.label){
270
281
  case 0:
@@ -272,10 +283,27 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
272
283
  tools = this.options.tools.map(function(tool) {
273
284
  return tool.getDynamicTool();
274
285
  });
286
+ // Add schema format instructions if schema is provided
287
+ schemaFormatInstructions = '';
288
+ if (this.options.schema) {
289
+ jsonSchema = z.toJSONSchema(this.options.schema);
290
+ isPrimitiveType = [
291
+ 'boolean',
292
+ 'integer',
293
+ 'number',
294
+ 'string'
295
+ ].includes(jsonSchema.type);
296
+ jsonSchemaString = JSON.stringify(jsonSchema, null, 2).replace(/{/g, '{{').replace(/}/g, '}}');
297
+ if (isPrimitiveType) {
298
+ schemaFormatInstructions = '\n\nSCHEMA VALIDATION: When providing a "RESPOND:" answer, the content after "RESPOND: " must be a '.concat(jsonSchema.type, " value that matches this schema:\n\n```json\n").concat(jsonSchemaString, '\n```\n\nExample format:\n```json\n{{\n "action": "Final Answer",\n "action_input": "RESPOND: your ').concat(jsonSchema.type, ' value here"\n}}\n```\n\nDo not wrap the ').concat(jsonSchema.type, ' value in JSON - just provide the raw value after "RESPOND: ".');
299
+ } else {
300
+ schemaFormatInstructions = '\n\nSCHEMA VALIDATION: When providing a "RESPOND:" answer, the content after "RESPOND: " must be valid JSON that matches this exact schema:\n\n```json\n'.concat(jsonSchemaString, '\n```\n\nExample format:\n```json\n{{\n "action": "Final Answer",\n "action_input": "RESPOND: {{\\"field1\\": \\"value1\\", \\"field2\\": \\"value2\\"}}"\n}}\n```\n');
301
+ }
302
+ }
275
303
  prompt = ChatPromptTemplate.fromMessages([
276
304
  [
277
305
  'system',
278
- SYSTEM_PROMPT_TEMPLATE.replace('{mission_prompt}', this.options.systemPrompt.generate())
306
+ SYSTEM_PROMPT_TEMPLATE.replace('{mission_prompt}', this.options.systemPrompt.generate()).replace('{schema_format}', schemaFormatInstructions)
279
307
  ],
280
308
  [
281
309
  'human',
@@ -332,9 +360,9 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
332
360
  },
333
361
  {
334
362
  key: "resolveUserInput",
335
- value: function resolveUserInput(userPrompt) {
336
- if (userPrompt) {
337
- return userPrompt.generate();
363
+ value: function resolveUserInput(input) {
364
+ if (input) {
365
+ return input.generate();
338
366
  }
339
367
  return 'Proceed with your instructions.';
340
368
  }
@@ -343,7 +371,7 @@ var SYSTEM_PROMPT_TEMPLATE = '\n<OBJECTIVE>\n{mission_prompt}\n</OBJECTIVE>\n\n<
343
371
  key: "validateResponseContent",
344
372
  value: function validateResponseContent(content, schema) {
345
373
  try {
346
- new AIResponseParser(schema).parse(content);
374
+ return new AIResponseParser(schema).parse(content);
347
375
  } catch (error) {
348
376
  var _this_options_logger;
349
377
  (_this_options_logger = this.options.logger) === null || _this_options_logger === void 0 ? void 0 : _this_options_logger.error("[".concat(this.name, "] Failed to validate response content against schema."), {