concevent-ai-agent-sdk 1.0.4 → 2.0.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.
- package/README.md +582 -2
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +153 -66
- package/dist/core/agent.js.map +1 -1
- package/dist/core/errors.d.ts +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +4 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/logger.d.ts +2 -0
- package/dist/core/logger.d.ts.map +1 -1
- package/dist/core/logger.js +8 -0
- package/dist/core/logger.js.map +1 -1
- package/dist/core/middleware.d.ts +55 -0
- package/dist/core/middleware.d.ts.map +1 -0
- package/dist/core/middleware.js +125 -0
- package/dist/core/middleware.js.map +1 -0
- package/dist/core/orchestrator.d.ts +31 -0
- package/dist/core/orchestrator.d.ts.map +1 -0
- package/dist/core/orchestrator.js +206 -0
- package/dist/core/orchestrator.js.map +1 -0
- package/dist/core/response-format.d.ts +44 -0
- package/dist/core/response-format.d.ts.map +1 -0
- package/dist/core/response-format.js +107 -0
- package/dist/core/response-format.js.map +1 -0
- package/dist/core/retry.d.ts +76 -0
- package/dist/core/retry.d.ts.map +1 -0
- package/dist/core/retry.js +164 -0
- package/dist/core/retry.js.map +1 -0
- package/dist/core/summarization.d.ts.map +1 -1
- package/dist/core/summarization.js +21 -3
- package/dist/core/summarization.js.map +1 -1
- package/dist/core/tool-executor.d.ts +18 -11
- package/dist/core/tool-executor.d.ts.map +1 -1
- package/dist/core/tool-executor.js +129 -18
- package/dist/core/tool-executor.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/types/config.d.ts +103 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +5 -1
- package/dist/types/config.js.map +1 -1
- package/dist/types/events.d.ts +24 -1
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/events.js.map +1 -1
- package/dist/types/index.d.ts +5 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/middleware.d.ts +115 -0
- package/dist/types/middleware.d.ts.map +1 -0
- package/dist/types/middleware.js +2 -0
- package/dist/types/middleware.js.map +1 -0
- package/dist/types/orchestrator.d.ts +61 -0
- package/dist/types/orchestrator.d.ts.map +1 -0
- package/dist/types/orchestrator.js +2 -0
- package/dist/types/orchestrator.js.map +1 -0
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -13,6 +13,9 @@ A framework-agnostic AI Agent SDK for building intelligent conversational agents
|
|
|
13
13
|
- ⛔ **Abort Support** - Cancel ongoing requests with AbortController
|
|
14
14
|
- 🔄 **Retry Logic** - Built-in retry mechanism for resilient operations
|
|
15
15
|
- 📝 **Reasoning Support** - Access model reasoning/thinking outputs
|
|
16
|
+
- 🔌 **Middleware System** - Extensible plugin architecture for logging, sanitization, and more
|
|
17
|
+
- 📋 **Structured Output** - JSON schema validation with Zod for type-safe responses
|
|
18
|
+
- 🎭 **Multi-Agent Orchestration** - Route tasks to specialized sub-agents based on their capabilities
|
|
16
19
|
|
|
17
20
|
## Installation
|
|
18
21
|
|
|
@@ -86,9 +89,14 @@ console.log(result.message);
|
|
|
86
89
|
- [Types](#types)
|
|
87
90
|
- [Streaming](#streaming)
|
|
88
91
|
- [Advanced Usage](#advanced-usage)
|
|
92
|
+
- [Parallel Tool Execution](#parallel-tool-execution)
|
|
89
93
|
- [Conversation Summarization](#conversation-summarization)
|
|
90
94
|
- [Error Handling](#error-handling)
|
|
95
|
+
- [Retry Configuration](#retry-configuration)
|
|
96
|
+
- [Structured Output](#structured-output)
|
|
91
97
|
- [Abort Requests](#abort-requests)
|
|
98
|
+
- [Middleware](#middleware)
|
|
99
|
+
- [Multi-Agent Orchestration](#multi-agent-orchestration)
|
|
92
100
|
|
|
93
101
|
---
|
|
94
102
|
|
|
@@ -137,7 +145,11 @@ const agent = createAgent(config: AgentConfig): Agent;
|
|
|
137
145
|
| `maxIterations` | `number` | ❌ | `20` | Maximum tool execution iterations per chat |
|
|
138
146
|
| `stream` | `boolean` | ❌ | `true` | Enable streaming responses with delta callbacks |
|
|
139
147
|
| `summarization` | `SummarizationConfig` | ❌ | `{ enabled: true }` | Summarization settings |
|
|
148
|
+
| `parallelToolExecution` | `ParallelExecutionConfig` | ❌ | `{ maxConcurrency: 5 }` | Parallel tool execution settings |
|
|
140
149
|
| `errorMessages` | `ErrorMessages` | ❌ | Default messages | Custom error messages |
|
|
150
|
+
| `retry` | `RetryConfig` | ❌ | `{ maxAttempts: 3 }` | Retry configuration for API failures and validation retries |
|
|
151
|
+
| `responseFormat` | `ResponseFormatConfig` | ❌ | `undefined` (text) | Structured output format (text, json_object, json_schema) |
|
|
152
|
+
| `middleware` | `Middleware[]` | ❌ | `[]` | Middleware array for intercepting agent behavior |
|
|
141
153
|
|
|
142
154
|
#### SummarizationConfig
|
|
143
155
|
|
|
@@ -149,6 +161,39 @@ interface SummarizationConfig {
|
|
|
149
161
|
}
|
|
150
162
|
```
|
|
151
163
|
|
|
164
|
+
#### ParallelExecutionConfig
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
interface ParallelExecutionConfig {
|
|
168
|
+
maxConcurrency?: number; // Default: 5 - Max parallel tools to run simultaneously
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### RetryConfig
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
interface RetryConfig {
|
|
176
|
+
maxAttempts?: number; // Default: 3 - Total attempts including initial (also used for validation retries)
|
|
177
|
+
baseDelayMs?: number; // Default: 1000 - Initial delay before first retry
|
|
178
|
+
maxDelayMs?: number; // Default: 30000 - Maximum delay cap
|
|
179
|
+
backoffMultiplier?: number; // Default: 2 - Exponential backoff multiplier
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### ResponseFormatConfig
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
type ResponseFormatConfig =
|
|
187
|
+
| { type: 'text' } // Default free-form text
|
|
188
|
+
| { type: 'json_object' } // JSON without validation
|
|
189
|
+
| {
|
|
190
|
+
type: 'json_schema';
|
|
191
|
+
schema: ZodType<unknown>; // Zod schema for validation
|
|
192
|
+
name?: string; // Schema name (default: 'response')
|
|
193
|
+
strict?: boolean; // Strict mode (default: true)
|
|
194
|
+
};
|
|
195
|
+
```
|
|
196
|
+
|
|
152
197
|
#### Example with Full Configuration
|
|
153
198
|
|
|
154
199
|
```typescript
|
|
@@ -221,8 +266,9 @@ const result = await agent.chat(
|
|
|
221
266
|
**Returns:** `AgentResult`
|
|
222
267
|
|
|
223
268
|
```typescript
|
|
224
|
-
interface AgentResult {
|
|
269
|
+
interface AgentResult<T = unknown> {
|
|
225
270
|
message: string; // Final response message
|
|
271
|
+
parsedResponse?: T; // Parsed/validated response (when using json_schema)
|
|
226
272
|
reasoning?: {
|
|
227
273
|
// Model's reasoning (if available)
|
|
228
274
|
text?: string;
|
|
@@ -308,6 +354,7 @@ Tools extend the agent's capabilities by allowing it to perform actions or retri
|
|
|
308
354
|
interface ToolDefinition {
|
|
309
355
|
declaration: FunctionDeclaration;
|
|
310
356
|
executor: ToolExecutor;
|
|
357
|
+
parallel?: boolean; // Set to true for tools safe to run concurrently (default: false)
|
|
311
358
|
}
|
|
312
359
|
|
|
313
360
|
interface FunctionDeclaration {
|
|
@@ -418,6 +465,7 @@ interface AgentCallbacks {
|
|
|
418
465
|
onSummarizationStart?: (originalMessageCount: number) => void;
|
|
419
466
|
onSummarizationEnd?: (summary: string, tokensEstimate: number) => void;
|
|
420
467
|
onIterationStart?: (iteration: number, maxIterations: number) => void;
|
|
468
|
+
onRetry?: (attempt: number, maxAttempts: number, error: Error, delayMs: number) => void;
|
|
421
469
|
onError?: (error: {
|
|
422
470
|
code: string;
|
|
423
471
|
message: string;
|
|
@@ -756,6 +804,61 @@ const reasoningDeltaEvent = createEvent("reasoning_delta", {
|
|
|
756
804
|
|
|
757
805
|
## Advanced Usage
|
|
758
806
|
|
|
807
|
+
### Parallel Tool Execution
|
|
808
|
+
|
|
809
|
+
Tools can be marked as safe for parallel execution using the `parallel` flag. When the model requests multiple tool calls, parallel-safe tools run concurrently while sequential tools run one at a time after the parallel batch completes.
|
|
810
|
+
|
|
811
|
+
```typescript
|
|
812
|
+
import { createAgent } from "concevent-ai-agent-sdk";
|
|
813
|
+
import type { ToolDefinition } from "concevent-ai-agent-sdk";
|
|
814
|
+
|
|
815
|
+
const tools: ToolDefinition[] = [
|
|
816
|
+
{
|
|
817
|
+
declaration: {
|
|
818
|
+
name: "readFile",
|
|
819
|
+
description: "Read contents of a file",
|
|
820
|
+
parametersJsonSchema: { /* ... */ },
|
|
821
|
+
},
|
|
822
|
+
executor: async (args) => { /* read file */ },
|
|
823
|
+
parallel: true, // ✅ Safe for concurrent execution
|
|
824
|
+
},
|
|
825
|
+
{
|
|
826
|
+
declaration: {
|
|
827
|
+
name: "fetchWeather",
|
|
828
|
+
description: "Get weather for a city",
|
|
829
|
+
parametersJsonSchema: { /* ... */ },
|
|
830
|
+
},
|
|
831
|
+
executor: async (args) => { /* API call */ },
|
|
832
|
+
parallel: true, // ✅ Independent API calls are safe
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
declaration: {
|
|
836
|
+
name: "writeFile",
|
|
837
|
+
description: "Write contents to a file",
|
|
838
|
+
parametersJsonSchema: { /* ... */ },
|
|
839
|
+
},
|
|
840
|
+
executor: async (args) => { /* write file */ },
|
|
841
|
+
// parallel defaults to false — runs sequentially
|
|
842
|
+
},
|
|
843
|
+
];
|
|
844
|
+
|
|
845
|
+
const agent = createAgent({
|
|
846
|
+
apiKey: process.env.API_KEY!,
|
|
847
|
+
model: "anthropic/claude-3.5-sonnet",
|
|
848
|
+
systemPrompts: ["You are a helpful assistant."],
|
|
849
|
+
tools,
|
|
850
|
+
parallelToolExecution: {
|
|
851
|
+
maxConcurrency: 3, // Optional: limit concurrent tools (default: 5)
|
|
852
|
+
},
|
|
853
|
+
});
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
**Execution Order:**
|
|
857
|
+
When the model requests `[readFile(a), readFile(b), writeFile(c), readFile(d)]`:
|
|
858
|
+
1. Parallel tools run concurrently: `readFile(a)`, `readFile(b)`, `readFile(d)`
|
|
859
|
+
2. Sequential tools run in order: `writeFile(c)`
|
|
860
|
+
3. All results are collected and returned to the model
|
|
861
|
+
|
|
759
862
|
### Conversation Summarization
|
|
760
863
|
|
|
761
864
|
When conversations become too long, the agent automatically summarizes them to stay within context limits.
|
|
@@ -841,7 +944,7 @@ await agent.chat("Do something", context, {
|
|
|
841
944
|
| ----------------------- | --------------------------- | ----------- |
|
|
842
945
|
| `API_KEY_REQUIRED` | API key not provided | No |
|
|
843
946
|
| `MODEL_REQUIRED` | Model name not provided | No |
|
|
844
|
-
| `EMPTY_RESPONSE` | API returned empty response |
|
|
947
|
+
| `EMPTY_RESPONSE` | API returned empty response | Yes |
|
|
845
948
|
| `REQUEST_ABORTED` | Request was aborted | No |
|
|
846
949
|
| `NO_RESPONSE` | No response from API | No |
|
|
847
950
|
| `NO_RESPONSE_MESSAGE` | Response missing message | No |
|
|
@@ -850,6 +953,181 @@ await agent.chat("Do something", context, {
|
|
|
850
953
|
| `SUMMARIZATION_FAILED` | Summarization failed | Yes |
|
|
851
954
|
| `GENERIC_ERROR` | Unknown error occurred | No |
|
|
852
955
|
|
|
956
|
+
### Retry Configuration
|
|
957
|
+
|
|
958
|
+
The SDK includes automatic retry logic with exponential backoff and jitter for handling transient API failures (e.g., rate limits, network errors).
|
|
959
|
+
|
|
960
|
+
#### Configuration
|
|
961
|
+
|
|
962
|
+
```typescript
|
|
963
|
+
const agent = createAgent({
|
|
964
|
+
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
965
|
+
model: "anthropic/claude-3.5-sonnet",
|
|
966
|
+
systemPrompts: ["You are a helpful assistant."],
|
|
967
|
+
tools: [],
|
|
968
|
+
retry: {
|
|
969
|
+
maxAttempts: 5, // Total attempts including initial (default: 3)
|
|
970
|
+
baseDelayMs: 1000, // Initial delay before first retry (default: 1000)
|
|
971
|
+
maxDelayMs: 30000, // Maximum delay cap (default: 30000)
|
|
972
|
+
backoffMultiplier: 2, // Exponential multiplier (default: 2)
|
|
973
|
+
},
|
|
974
|
+
});
|
|
975
|
+
```
|
|
976
|
+
|
|
977
|
+
#### How It Works
|
|
978
|
+
|
|
979
|
+
1. **Exponential Backoff**: Delay doubles with each retry attempt
|
|
980
|
+
2. **Jitter**: Random ±25% variation prevents thundering herd problems
|
|
981
|
+
3. **Retry-After Support**: Honors server-provided `Retry-After` headers
|
|
982
|
+
4. **Abort Integration**: Respects abort signals during retry delays
|
|
983
|
+
|
|
984
|
+
**Delay Calculation:**
|
|
985
|
+
```
|
|
986
|
+
delay = min(baseDelayMs * (backoffMultiplier ^ attempt), maxDelayMs) * jitter
|
|
987
|
+
```
|
|
988
|
+
|
|
989
|
+
For example, with defaults (base=1000ms, multiplier=2, max=30000ms):
|
|
990
|
+
- Retry 1: ~1000ms (±250ms jitter)
|
|
991
|
+
- Retry 2: ~2000ms (±500ms jitter)
|
|
992
|
+
- Retry 3: ~4000ms (±1000ms jitter)
|
|
993
|
+
|
|
994
|
+
#### Retry Callback
|
|
995
|
+
|
|
996
|
+
Monitor retry attempts using the `onRetry` callback:
|
|
997
|
+
|
|
998
|
+
```typescript
|
|
999
|
+
await agent.chat("Hello", context, {
|
|
1000
|
+
onRetry: (attempt, maxAttempts, error, delayMs) => {
|
|
1001
|
+
console.log(`Retry ${attempt}/${maxAttempts} after ${delayMs}ms`);
|
|
1002
|
+
console.log(`Error: ${error.message}`);
|
|
1003
|
+
},
|
|
1004
|
+
});
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
#### Retryable Errors
|
|
1008
|
+
|
|
1009
|
+
The following HTTP status codes trigger automatic retries:
|
|
1010
|
+
- `408` - Request Timeout
|
|
1011
|
+
- `429` - Too Many Requests (Rate Limited)
|
|
1012
|
+
- `500` - Internal Server Error
|
|
1013
|
+
- `502` - Bad Gateway
|
|
1014
|
+
- `503` - Service Unavailable
|
|
1015
|
+
- `504` - Gateway Timeout
|
|
1016
|
+
|
|
1017
|
+
### Structured Output
|
|
1018
|
+
|
|
1019
|
+
The SDK supports structured JSON output with automatic Zod schema validation. This ensures type-safe responses from the AI model.
|
|
1020
|
+
|
|
1021
|
+
#### Response Format Types
|
|
1022
|
+
|
|
1023
|
+
| Type | Description | Validation |
|
|
1024
|
+
|------|-------------|------------|
|
|
1025
|
+
| `text` | Default free-form text response | None |
|
|
1026
|
+
| `json_object` | Forces JSON response | JSON parsing only |
|
|
1027
|
+
| `json_schema` | Forces JSON with schema validation | Zod schema validation |
|
|
1028
|
+
|
|
1029
|
+
#### Basic JSON Mode
|
|
1030
|
+
|
|
1031
|
+
Force the model to return valid JSON without schema validation:
|
|
1032
|
+
|
|
1033
|
+
```typescript
|
|
1034
|
+
const agent = createAgent({
|
|
1035
|
+
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
1036
|
+
model: "anthropic/claude-3.5-sonnet",
|
|
1037
|
+
systemPrompts: ["Return responses as JSON objects."],
|
|
1038
|
+
tools: [],
|
|
1039
|
+
responseFormat: { type: "json_object" },
|
|
1040
|
+
});
|
|
1041
|
+
|
|
1042
|
+
const result = await agent.chat("List 3 colors", context);
|
|
1043
|
+
// result.message: '{"colors": ["red", "blue", "green"]}'
|
|
1044
|
+
```
|
|
1045
|
+
|
|
1046
|
+
#### Schema-Validated JSON
|
|
1047
|
+
|
|
1048
|
+
Define a Zod schema for type-safe, validated responses:
|
|
1049
|
+
|
|
1050
|
+
```typescript
|
|
1051
|
+
import { z } from "zod";
|
|
1052
|
+
|
|
1053
|
+
// Define the expected response structure
|
|
1054
|
+
const WeatherSchema = z.object({
|
|
1055
|
+
location: z.string(),
|
|
1056
|
+
temperature: z.number(),
|
|
1057
|
+
unit: z.enum(["celsius", "fahrenheit"]),
|
|
1058
|
+
conditions: z.array(z.string()),
|
|
1059
|
+
});
|
|
1060
|
+
|
|
1061
|
+
type WeatherResponse = z.infer<typeof WeatherSchema>;
|
|
1062
|
+
|
|
1063
|
+
const agent = createAgent({
|
|
1064
|
+
apiKey: process.env.OPENROUTER_API_KEY!,
|
|
1065
|
+
model: "anthropic/claude-3.5-sonnet",
|
|
1066
|
+
systemPrompts: ["You provide weather information."],
|
|
1067
|
+
tools: [],
|
|
1068
|
+
responseFormat: {
|
|
1069
|
+
type: "json_schema",
|
|
1070
|
+
schema: WeatherSchema,
|
|
1071
|
+
name: "WeatherResponse", // Optional: schema name for API
|
|
1072
|
+
strict: true, // Optional: strict mode (default: true)
|
|
1073
|
+
},
|
|
1074
|
+
});
|
|
1075
|
+
|
|
1076
|
+
const result = await agent.chat("Weather in Tokyo", context);
|
|
1077
|
+
|
|
1078
|
+
// Access typed, validated response
|
|
1079
|
+
const weather = result.parsedResponse as WeatherResponse;
|
|
1080
|
+
console.log(weather.temperature); // Typed as number
|
|
1081
|
+
console.log(weather.conditions); // Typed as string[]
|
|
1082
|
+
```
|
|
1083
|
+
|
|
1084
|
+
#### Validation Retries
|
|
1085
|
+
|
|
1086
|
+
When schema validation fails, the SDK can automatically retry with error feedback. This uses the same `retry` configuration as API failures:
|
|
1087
|
+
|
|
1088
|
+
```typescript
|
|
1089
|
+
const agent = createAgent({
|
|
1090
|
+
// ... config
|
|
1091
|
+
responseFormat: {
|
|
1092
|
+
type: "json_schema",
|
|
1093
|
+
schema: MySchema,
|
|
1094
|
+
},
|
|
1095
|
+
retry: { maxAttempts: 3 }, // 3 total attempts (2 validation retries)
|
|
1096
|
+
});
|
|
1097
|
+
```
|
|
1098
|
+
|
|
1099
|
+
When validation fails:
|
|
1100
|
+
1. The SDK captures the Zod validation error
|
|
1101
|
+
2. Sends the error details back to the model as feedback
|
|
1102
|
+
3. Model attempts to generate a corrected response
|
|
1103
|
+
4. Process repeats until validation passes or retries exhausted
|
|
1104
|
+
|
|
1105
|
+
#### Custom Error Messages
|
|
1106
|
+
|
|
1107
|
+
Customize validation error messages:
|
|
1108
|
+
|
|
1109
|
+
```typescript
|
|
1110
|
+
const agent = createAgent({
|
|
1111
|
+
// ... config
|
|
1112
|
+
errorMessages: {
|
|
1113
|
+
jsonParseError: "Failed to parse JSON response",
|
|
1114
|
+
responseSchemaValidationFailed: "Response didn't match expected format",
|
|
1115
|
+
},
|
|
1116
|
+
});
|
|
1117
|
+
```
|
|
1118
|
+
|
|
1119
|
+
#### AgentResult with Parsed Response
|
|
1120
|
+
|
|
1121
|
+
When using `json_schema` format, `AgentResult` includes the validated data:
|
|
1122
|
+
|
|
1123
|
+
```typescript
|
|
1124
|
+
interface AgentResult<T = unknown> {
|
|
1125
|
+
message: string; // Raw JSON string
|
|
1126
|
+
parsedResponse?: T; // Parsed & validated object (only with json_schema)
|
|
1127
|
+
// ... other fields
|
|
1128
|
+
}
|
|
1129
|
+
```
|
|
1130
|
+
|
|
853
1131
|
### Abort Requests
|
|
854
1132
|
|
|
855
1133
|
Cancel ongoing requests using the abort functionality.
|
|
@@ -964,6 +1242,288 @@ async function sendMessage(message: string) {
|
|
|
964
1242
|
|
|
965
1243
|
> **Note:** The SDK handles summarization automatically when context limits are approached. The summarized history is included in `result.conversationHistory`, so clients always receive the properly managed history state.
|
|
966
1244
|
|
|
1245
|
+
### Middleware
|
|
1246
|
+
|
|
1247
|
+
Middleware allows you to intercept and modify the agent's execution flow at key points. Use middleware for logging, analytics, rate limiting, input sanitization, and output filtering.
|
|
1248
|
+
|
|
1249
|
+
#### Middleware Interface
|
|
1250
|
+
|
|
1251
|
+
```typescript
|
|
1252
|
+
import type { Middleware } from "concevent-ai-agent-sdk";
|
|
1253
|
+
|
|
1254
|
+
interface Middleware {
|
|
1255
|
+
name: string;
|
|
1256
|
+
beforeChat?: (ctx: BeforeChatContext) => Promise<string>;
|
|
1257
|
+
afterChat?: (ctx: AfterChatContext) => Promise<AgentResult>;
|
|
1258
|
+
beforeToolCall?: (ctx: BeforeToolCallContext) => Promise<ToolCall>;
|
|
1259
|
+
afterToolCall?: (ctx: AfterToolCallContext) => Promise<FunctionCallResult>;
|
|
1260
|
+
onError?: (ctx: ErrorContext) => Promise<void>;
|
|
1261
|
+
}
|
|
1262
|
+
```
|
|
1263
|
+
|
|
1264
|
+
#### Middleware Hooks
|
|
1265
|
+
|
|
1266
|
+
| Hook | When Called | Can Modify |
|
|
1267
|
+
|------|-------------|------------|
|
|
1268
|
+
| `beforeChat` | Before chat processing begins | User message |
|
|
1269
|
+
| `afterChat` | After chat completes successfully | AgentResult |
|
|
1270
|
+
| `beforeToolCall` | Before each tool executes | ToolCall args |
|
|
1271
|
+
| `afterToolCall` | After each tool executes | FunctionCallResult |
|
|
1272
|
+
| `onError` | When an error occurs | Observation only |
|
|
1273
|
+
|
|
1274
|
+
#### Creating Middleware
|
|
1275
|
+
|
|
1276
|
+
```typescript
|
|
1277
|
+
import { createAgent } from "concevent-ai-agent-sdk";
|
|
1278
|
+
import type { Middleware } from "concevent-ai-agent-sdk";
|
|
1279
|
+
|
|
1280
|
+
// Logging middleware
|
|
1281
|
+
const loggingMiddleware: Middleware = {
|
|
1282
|
+
name: "logging",
|
|
1283
|
+
beforeChat: async (ctx) => {
|
|
1284
|
+
console.log(`[${new Date().toISOString()}] Chat started:`, ctx.message);
|
|
1285
|
+
return ctx.message;
|
|
1286
|
+
},
|
|
1287
|
+
afterChat: async (ctx) => {
|
|
1288
|
+
console.log(`[${new Date().toISOString()}] Chat completed:`, ctx.result.message);
|
|
1289
|
+
return ctx.result;
|
|
1290
|
+
},
|
|
1291
|
+
beforeToolCall: async (ctx) => {
|
|
1292
|
+
console.log(`[${new Date().toISOString()}] Tool call:`, ctx.toolCall.name);
|
|
1293
|
+
return ctx.toolCall;
|
|
1294
|
+
},
|
|
1295
|
+
onError: async (ctx) => {
|
|
1296
|
+
console.error(`[${new Date().toISOString()}] Error:`, ctx.error.code, ctx.error.message);
|
|
1297
|
+
},
|
|
1298
|
+
};
|
|
1299
|
+
|
|
1300
|
+
// Input sanitization middleware
|
|
1301
|
+
const sanitizationMiddleware: Middleware = {
|
|
1302
|
+
name: "sanitization",
|
|
1303
|
+
beforeChat: async (ctx) => {
|
|
1304
|
+
// Remove potentially harmful content from user input
|
|
1305
|
+
const sanitized = ctx.message.replace(/<script[^>]*>.*?<\/script>/gi, "");
|
|
1306
|
+
return sanitized;
|
|
1307
|
+
},
|
|
1308
|
+
};
|
|
1309
|
+
|
|
1310
|
+
// Rate limiting middleware
|
|
1311
|
+
const rateLimitMiddleware: Middleware = {
|
|
1312
|
+
name: "rate-limit",
|
|
1313
|
+
beforeChat: async (ctx) => {
|
|
1314
|
+
const userId = ctx.toolContext.userId;
|
|
1315
|
+
if (await isRateLimited(userId)) {
|
|
1316
|
+
throw new Error("Rate limit exceeded. Please try again later.");
|
|
1317
|
+
}
|
|
1318
|
+
return ctx.message;
|
|
1319
|
+
},
|
|
1320
|
+
};
|
|
1321
|
+
|
|
1322
|
+
// Output filtering middleware
|
|
1323
|
+
const outputFilterMiddleware: Middleware = {
|
|
1324
|
+
name: "output-filter",
|
|
1325
|
+
afterChat: async (ctx) => {
|
|
1326
|
+
// Remove sensitive data from responses
|
|
1327
|
+
const filteredMessage = ctx.result.message.replace(/\b\d{3}-\d{2}-\d{4}\b/g, "[REDACTED]");
|
|
1328
|
+
return { ...ctx.result, message: filteredMessage };
|
|
1329
|
+
},
|
|
1330
|
+
afterToolCall: async (ctx) => {
|
|
1331
|
+
// Filter sensitive data from tool results
|
|
1332
|
+
if (typeof ctx.result.result === "object" && ctx.result.result !== null) {
|
|
1333
|
+
const filtered = JSON.parse(
|
|
1334
|
+
JSON.stringify(ctx.result.result).replace(/"password":\s*"[^"]*"/g, '"password": "[REDACTED]"')
|
|
1335
|
+
);
|
|
1336
|
+
return { ...ctx.result, result: filtered };
|
|
1337
|
+
}
|
|
1338
|
+
return ctx.result;
|
|
1339
|
+
},
|
|
1340
|
+
};
|
|
1341
|
+
```
|
|
1342
|
+
|
|
1343
|
+
#### Registering Middleware
|
|
1344
|
+
|
|
1345
|
+
Middleware is registered via the `middleware` property in `AgentConfig`. Middleware executes in registration order (first in array = first executed).
|
|
1346
|
+
|
|
1347
|
+
```typescript
|
|
1348
|
+
const agent = createAgent({
|
|
1349
|
+
apiKey: process.env.API_KEY!,
|
|
1350
|
+
model: "anthropic/claude-3.5-sonnet",
|
|
1351
|
+
systemPrompts: ["You are a helpful assistant."],
|
|
1352
|
+
tools: myTools,
|
|
1353
|
+
middleware: [
|
|
1354
|
+
loggingMiddleware, // Executes first
|
|
1355
|
+
sanitizationMiddleware, // Executes second
|
|
1356
|
+
rateLimitMiddleware, // Executes third
|
|
1357
|
+
outputFilterMiddleware, // Executes fourth
|
|
1358
|
+
],
|
|
1359
|
+
});
|
|
1360
|
+
```
|
|
1361
|
+
|
|
1362
|
+
#### Middleware Context
|
|
1363
|
+
|
|
1364
|
+
Each middleware hook receives a context object with relevant information:
|
|
1365
|
+
|
|
1366
|
+
```typescript
|
|
1367
|
+
// BeforeChatContext & AfterChatContext
|
|
1368
|
+
interface MiddlewareContext {
|
|
1369
|
+
message: string; // The user's input message
|
|
1370
|
+
history: ChatMessage[]; // Current conversation history
|
|
1371
|
+
toolContext: ToolExecutorContext; // userId, timezone, abortSignal
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
// BeforeToolCallContext (extends MiddlewareContext)
|
|
1375
|
+
interface BeforeToolCallContext extends MiddlewareContext {
|
|
1376
|
+
toolCall: ToolCall; // The tool call to be executed
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
// AfterToolCallContext (extends BeforeToolCallContext)
|
|
1380
|
+
interface AfterToolCallContext extends BeforeToolCallContext {
|
|
1381
|
+
result: FunctionCallResult; // The tool execution result
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
// AfterChatContext (extends MiddlewareContext)
|
|
1385
|
+
interface AfterChatContext extends MiddlewareContext {
|
|
1386
|
+
result: AgentResult; // The chat result
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
// ErrorContext (extends MiddlewareContext)
|
|
1390
|
+
interface ErrorContext extends MiddlewareContext {
|
|
1391
|
+
error: AgentError; // The error that occurred
|
|
1392
|
+
}
|
|
1393
|
+
```
|
|
1394
|
+
|
|
1395
|
+
#### Error Handling in Middleware
|
|
1396
|
+
|
|
1397
|
+
- If a middleware hook throws an error, the error propagates and stops the chain
|
|
1398
|
+
- `onError` hooks are called for observation only and do not affect the error flow
|
|
1399
|
+
- Errors in `onError` hooks are logged but do not throw
|
|
1400
|
+
|
|
1401
|
+
### Multi-Agent Orchestration
|
|
1402
|
+
|
|
1403
|
+
The SDK supports multi-agent orchestration, allowing you to create specialized agents and have an orchestrator agent route tasks to them based on their capabilities.
|
|
1404
|
+
|
|
1405
|
+
#### Creating an Orchestrator
|
|
1406
|
+
|
|
1407
|
+
```typescript
|
|
1408
|
+
import { createAgent, createOrchestratorAgent } from "concevent-ai-agent-sdk";
|
|
1409
|
+
import type { AgentDefinition } from "concevent-ai-agent-sdk";
|
|
1410
|
+
|
|
1411
|
+
// Create specialized sub-agents
|
|
1412
|
+
const codeAgent = createAgent({
|
|
1413
|
+
apiKey: process.env.API_KEY!,
|
|
1414
|
+
model: "anthropic/claude-3.5-sonnet",
|
|
1415
|
+
systemPrompts: ["You are an expert programmer. Write clean, efficient code."],
|
|
1416
|
+
tools: codingTools,
|
|
1417
|
+
});
|
|
1418
|
+
|
|
1419
|
+
const researchAgent = createAgent({
|
|
1420
|
+
apiKey: process.env.API_KEY!,
|
|
1421
|
+
model: "anthropic/claude-3.5-sonnet",
|
|
1422
|
+
systemPrompts: ["You are a research specialist. Find accurate information."],
|
|
1423
|
+
tools: researchTools,
|
|
1424
|
+
});
|
|
1425
|
+
|
|
1426
|
+
const dataAgent = createAgent({
|
|
1427
|
+
apiKey: process.env.API_KEY!,
|
|
1428
|
+
model: "anthropic/claude-3.5-sonnet",
|
|
1429
|
+
systemPrompts: ["You are a data analyst. Analyze data and provide insights."],
|
|
1430
|
+
tools: analysisTools,
|
|
1431
|
+
});
|
|
1432
|
+
|
|
1433
|
+
// Define sub-agents with descriptions
|
|
1434
|
+
const subAgents: AgentDefinition[] = [
|
|
1435
|
+
{
|
|
1436
|
+
agent: codeAgent,
|
|
1437
|
+
name: "code_expert",
|
|
1438
|
+
description: "Handles coding tasks: writing, reviewing, and debugging code",
|
|
1439
|
+
parallel: true, // Can run in parallel with other parallel agents
|
|
1440
|
+
},
|
|
1441
|
+
{
|
|
1442
|
+
agent: researchAgent,
|
|
1443
|
+
name: "researcher",
|
|
1444
|
+
description: "Researches topics, finds documentation, and gathers information",
|
|
1445
|
+
parallel: true,
|
|
1446
|
+
},
|
|
1447
|
+
{
|
|
1448
|
+
agent: dataAgent,
|
|
1449
|
+
name: "data_analyst",
|
|
1450
|
+
description: "Analyzes data, creates visualizations, and provides statistical insights",
|
|
1451
|
+
},
|
|
1452
|
+
];
|
|
1453
|
+
|
|
1454
|
+
// Create the orchestrator
|
|
1455
|
+
const orchestrator = createOrchestratorAgent({
|
|
1456
|
+
apiKey: process.env.API_KEY!,
|
|
1457
|
+
model: "anthropic/claude-3.5-sonnet",
|
|
1458
|
+
systemPrompts: ["Additional instructions for the orchestrator..."],
|
|
1459
|
+
subAgents,
|
|
1460
|
+
});
|
|
1461
|
+
```
|
|
1462
|
+
|
|
1463
|
+
#### Using the Orchestrator
|
|
1464
|
+
|
|
1465
|
+
The orchestrator automatically routes requests to appropriate sub-agents:
|
|
1466
|
+
|
|
1467
|
+
```typescript
|
|
1468
|
+
// The orchestrator decides which sub-agent(s) to use
|
|
1469
|
+
const result = await orchestrator.chat(
|
|
1470
|
+
"Research the best sorting algorithms and implement quicksort in TypeScript",
|
|
1471
|
+
{ userId: "user-123", timezone: "UTC" },
|
|
1472
|
+
{
|
|
1473
|
+
// Track sub-agent delegation
|
|
1474
|
+
onSubAgentStart: (data) => {
|
|
1475
|
+
console.log(`Delegating to ${data.agentName}: ${data.message}`);
|
|
1476
|
+
},
|
|
1477
|
+
onSubAgentComplete: (data) => {
|
|
1478
|
+
console.log(`${data.agentName} completed in ${data.result.iterations} iterations`);
|
|
1479
|
+
},
|
|
1480
|
+
// Standard callbacks also work
|
|
1481
|
+
onToolCallStart: (calls) => {
|
|
1482
|
+
console.log("Tool calls:", calls.map(c => c.name));
|
|
1483
|
+
},
|
|
1484
|
+
}
|
|
1485
|
+
);
|
|
1486
|
+
```
|
|
1487
|
+
|
|
1488
|
+
#### OrchestratorConfig
|
|
1489
|
+
|
|
1490
|
+
| Property | Type | Required | Default | Description |
|
|
1491
|
+
|-----------------|---------------------|----------|-------------------|----------------------------------------------|
|
|
1492
|
+
| `apiKey` | `string` | ✅ | - | API key for the orchestrator |
|
|
1493
|
+
| `model` | `string` | ✅ | - | Model for the orchestrator |
|
|
1494
|
+
| `systemPrompts` | `string[]` | ✅ | - | Additional prompts (orchestrator prompt auto-injected) |
|
|
1495
|
+
| `subAgents` | `AgentDefinition[]` | ✅ | - | Array of sub-agent definitions |
|
|
1496
|
+
| *(other)* | - | - | Same as AgentConfig | All other AgentConfig options except `tools` |
|
|
1497
|
+
|
|
1498
|
+
#### AgentDefinition
|
|
1499
|
+
|
|
1500
|
+
```typescript
|
|
1501
|
+
interface AgentDefinition {
|
|
1502
|
+
agent: Agent; // The agent instance
|
|
1503
|
+
name: string; // Unique name (used as tool name)
|
|
1504
|
+
description: string; // Describes capabilities (helps routing)
|
|
1505
|
+
parallel?: boolean; // Can run in parallel (default: false)
|
|
1506
|
+
}
|
|
1507
|
+
```
|
|
1508
|
+
|
|
1509
|
+
#### OrchestratorAgent Interface
|
|
1510
|
+
|
|
1511
|
+
```typescript
|
|
1512
|
+
interface OrchestratorAgent extends Agent {
|
|
1513
|
+
getSubAgents(): AgentDefinition[]; // Returns registered sub-agents
|
|
1514
|
+
}
|
|
1515
|
+
```
|
|
1516
|
+
|
|
1517
|
+
#### Key Concepts
|
|
1518
|
+
|
|
1519
|
+
1. **Stateless Delegation**: Sub-agents have their history cleared before each delegation. The orchestrator must include all necessary context in the delegated message.
|
|
1520
|
+
|
|
1521
|
+
2. **Parallel Execution**: Sub-agents marked with `parallel: true` can be called concurrently when the orchestrator needs multiple specialists.
|
|
1522
|
+
|
|
1523
|
+
3. **No Nested Orchestrators**: Sub-agents cannot themselves be orchestrators. This prevents infinite delegation loops.
|
|
1524
|
+
|
|
1525
|
+
4. **Automatic Routing**: The orchestrator's LLM decides which sub-agent(s) to use based on their descriptions and the user's request.
|
|
1526
|
+
|
|
967
1527
|
---
|
|
968
1528
|
|
|
969
1529
|
## Exports Summary
|
|
@@ -973,6 +1533,7 @@ async function sendMessage(message: string) {
|
|
|
973
1533
|
```typescript
|
|
974
1534
|
// Functions
|
|
975
1535
|
export { createAgent } from "./core/agent";
|
|
1536
|
+
export { createOrchestratorAgent } from "./core/orchestrator";
|
|
976
1537
|
export { createEvent } from "./types/events";
|
|
977
1538
|
|
|
978
1539
|
// Constants
|
|
@@ -987,6 +1548,8 @@ export type {
|
|
|
987
1548
|
ToolExecutorContext,
|
|
988
1549
|
ToolDefinition,
|
|
989
1550
|
AgentConfig,
|
|
1551
|
+
ParallelExecutionConfig,
|
|
1552
|
+
RetryConfig,
|
|
990
1553
|
UsageMetadata,
|
|
991
1554
|
AgentResult,
|
|
992
1555
|
ToolCallStartData,
|
|
@@ -995,11 +1558,28 @@ export type {
|
|
|
995
1558
|
AgentEventType,
|
|
996
1559
|
ThinkingEventData,
|
|
997
1560
|
UsageUpdateEventData,
|
|
1561
|
+
RetryEventData,
|
|
998
1562
|
ErrorEventData,
|
|
999
1563
|
CompleteEventData,
|
|
1000
1564
|
MessageDeltaEventData,
|
|
1001
1565
|
ReasoningDeltaEventData,
|
|
1002
1566
|
AgentEvent,
|
|
1567
|
+
ResponseFormatConfig,
|
|
1568
|
+
// Middleware types
|
|
1569
|
+
Middleware,
|
|
1570
|
+
MiddlewareContext,
|
|
1571
|
+
BeforeChatContext,
|
|
1572
|
+
AfterChatContext,
|
|
1573
|
+
BeforeToolCallContext,
|
|
1574
|
+
AfterToolCallContext,
|
|
1575
|
+
ErrorContext,
|
|
1576
|
+
// Orchestrator types
|
|
1577
|
+
AgentDefinition,
|
|
1578
|
+
OrchestratorConfig,
|
|
1579
|
+
OrchestratorAgent,
|
|
1580
|
+
SubAgentStartData,
|
|
1581
|
+
SubAgentCompleteData,
|
|
1582
|
+
OrchestratorCallbacks,
|
|
1003
1583
|
} from "./types";
|
|
1004
1584
|
```
|
|
1005
1585
|
|
package/dist/core/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,aAAa,
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,aAAa,EAId,MAAM,mBAAmB,CAAC;AAqD3B,MAAM,WAAW,KAAK;IACpB,IAAI,CACF,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,mBAAmB,EAC5B,SAAS,CAAC,EAAE,cAAc,GACzB,OAAO,CAAC,WAAW,CAAC,CAAC;IACxB,KAAK,IAAI,IAAI,CAAC;IACd,UAAU,IAAI,WAAW,EAAE,CAAC;IAC5B,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IACzC,YAAY,IAAI,IAAI,CAAC;IACrB,aAAa,IAAI,aAAa,CAAC;CAChC;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,CA8pBtD"}
|