@statelyai/agent 1.0.0 → 1.1.2

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.
@@ -7,18 +7,18 @@ runs:
7
7
  - uses: actions/setup-node@v4
8
8
  with:
9
9
  node-version: 20.x
10
+
11
+ - name: install pnpm
12
+ run: npm i pnpm@latest -g
13
+ shell: bash
10
14
 
11
- - name: Get pnpm store directory
15
+ - name: Setup npmrc
16
+ run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc
12
17
  shell: bash
13
- id: pnpm-cache
14
- run: |
15
- echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
16
- - uses: actions/cache@v4
17
- name: Setup pnpm cache
18
- with:
19
- path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
20
- key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
21
- restore-keys: |
22
- ${{ runner.os }}-pnpm-store-
18
+
19
+ - name: setup pnpm config
20
+ run: pnpm config set store-dir $PNPM_CACHE_FOLDER
21
+ shell: bash
22
+
23
23
  - run: pnpm install
24
24
  shell: bash
@@ -22,14 +22,26 @@ jobs:
22
22
  runs-on: ubuntu-latest
23
23
 
24
24
  steps:
25
- - uses: actions/checkout@v4
26
- - uses: ./.github/actions/ci-setup
27
-
28
- - name: Create Release Pull Request or Publish to npm
25
+ - name: checkout code repository
26
+ uses: actions/checkout@v3
27
+ with:
28
+ fetch-depth: 0
29
+ - name: setup node.js
30
+ uses: actions/setup-node@v3
31
+ with:
32
+ node-version: 20
33
+ - name: install pnpm
34
+ run: npm i pnpm@latest -g
35
+ - name: Setup npmrc
36
+ run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc
37
+ - name: setup pnpm config
38
+ run: pnpm config set store-dir $PNPM_CACHE_FOLDER
39
+ - name: install dependencies
40
+ run: pnpm install
41
+ - name: create and publish versions
29
42
  uses: changesets/action@v1
30
43
  with:
31
44
  publish: pnpm run release
32
45
  version: pnpm run version
33
46
  env:
34
47
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
package/CHANGELOG.md CHANGED
@@ -1,5 +1,90 @@
1
1
  # @statelyai/agent
2
2
 
3
+ ## 1.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#43](https://github.com/statelyai/agent/pull/43) [`8e7629c`](https://github.com/statelyai/agent/commit/8e7629c347b29b704ae9576aa1af97e6cd693bc7) Thanks [@davidkpiano](https://github.com/davidkpiano)! - Update dependencies
8
+
9
+ ## 1.1.1
10
+
11
+ ### Patch Changes
12
+
13
+ - [#41](https://github.com/statelyai/agent/pull/41) [`b2f2b73`](https://github.com/statelyai/agent/commit/b2f2b7307e96d7722968769aae9db2572ede8ce7) Thanks [@davidkpiano](https://github.com/davidkpiano)! - Update dependencies
14
+
15
+ ## 1.1.0
16
+
17
+ ### Minor Changes
18
+
19
+ - [#39](https://github.com/statelyai/agent/pull/39) [`3cce30f`](https://github.com/statelyai/agent/commit/3cce30fc77d36dbed0abad805248de9f64bf8086) Thanks [@davidkpiano](https://github.com/davidkpiano)! - Added four new methods for easily retrieving agent messages, observations, feedback, and plans:
20
+
21
+ - `agent.getMessages()`
22
+ - `agent.getObservations()`
23
+ - `agent.getFeedback()`
24
+ - `agent.getPlans()`
25
+
26
+ The `agent.select(…)` method is deprecated in favor of these methods.
27
+
28
+ - [#40](https://github.com/statelyai/agent/pull/40) [`8b7c374`](https://github.com/statelyai/agent/commit/8b7c37482d5c35b2b3addc2f88e198526f203da7) Thanks [@davidkpiano](https://github.com/davidkpiano)! - Correlation IDs are now provided as part of the result from `agent.generateText(…)` and `agent.streamText(…)`:
29
+
30
+ ```ts
31
+ const result = await agent.generateText({
32
+ prompt: "Write me a song",
33
+ correlationId: "my-correlation-id",
34
+ // ...
35
+ });
36
+
37
+ result.correlationId; // 'my-correlation-id'
38
+ ```
39
+
40
+ These correlation IDs can be passed to feedback:
41
+
42
+ ```ts
43
+ // ...
44
+
45
+ agent.addFeedback({
46
+ reward: -1,
47
+ correlationId: result.correlationId,
48
+ });
49
+ ```
50
+
51
+ - [#40](https://github.com/statelyai/agent/pull/40) [`8b7c374`](https://github.com/statelyai/agent/commit/8b7c37482d5c35b2b3addc2f88e198526f203da7) Thanks [@davidkpiano](https://github.com/davidkpiano)! - Changes to agent feedback (the `AgentFeedback` interface):
52
+
53
+ - `goal` is now optional
54
+ - `observationId` is now optional
55
+ - `correlationId` has been added (optional)
56
+ - `reward` has been added (optional)
57
+ - `attributes` are now optional
58
+
59
+ - [#38](https://github.com/statelyai/agent/pull/38) [`21fb17c`](https://github.com/statelyai/agent/commit/21fb17c65fac1cbb4a8b08a04a58480a6930a0a9) Thanks [@davidkpiano](https://github.com/davidkpiano)! - You can now add `context` Zod schema to your agent. For now, this is meant to be passed directly to the state machine, but in the future, the schema can be shared with the LLM agent to better understand the state machine and its context for decision making.
60
+
61
+ Breaking: The `context` and `events` types are now in `agent.types` instead of ~~`agent.eventTypes`.
62
+
63
+ ```ts
64
+ const agent = createAgent({
65
+ // ...
66
+ context: {
67
+ score: z.number().describe("The score of the game"),
68
+ // ...
69
+ },
70
+ });
71
+
72
+ const machine = setup({
73
+ types: agent.types,
74
+ }).createMachine({
75
+ context: {
76
+ score: 0,
77
+ },
78
+ // ...
79
+ });
80
+ ```
81
+
82
+ ### Patch Changes
83
+
84
+ - [`5f863bb`](https://github.com/statelyai/agent/commit/5f863bb0d89d90f30d0a9aa1f0dd2a35f0eeb45b) Thanks [@davidkpiano](https://github.com/davidkpiano)! - Use nanoid
85
+
86
+ - [#37](https://github.com/statelyai/agent/pull/37) [`dafa815`](https://github.com/statelyai/agent/commit/dafa8157cc1b5adbfb222c146dbc84ab2eed8894) Thanks [@davidkpiano](https://github.com/davidkpiano)! - Messages are now properly included in `agent.decide(…)`, when specified.
87
+
3
88
  ## 0.1.0
4
89
 
5
90
  ### Minor Changes
package/dist/index.d.mts CHANGED
@@ -97,17 +97,24 @@ type AgentDecideOptions = {
97
97
  events?: ZodEventMapping;
98
98
  } & Omit<Parameters<typeof generateText>[0], 'model' | 'tools' | 'prompt' | 'messages'>;
99
99
  interface AgentFeedback {
100
- goal: string;
101
- observationId: string;
100
+ goal?: string;
101
+ observationId?: string;
102
+ /**
103
+ * The message correlation that the feedback is relevant for
104
+ */
105
+ correlationId?: string;
102
106
  attributes: Record<string, any>;
107
+ reward: number;
103
108
  timestamp: number;
104
109
  sessionId: string;
105
110
  }
106
111
  interface AgentFeedbackInput {
107
- goal: string;
108
- observationId: string;
109
- attributes: Record<string, any>;
112
+ goal?: string;
113
+ observationId?: string;
114
+ correlationId?: string;
115
+ attributes?: Record<string, any>;
110
116
  timestamp?: number;
117
+ reward?: number;
111
118
  }
112
119
  type AgentMessage = CoreMessage & {
113
120
  timestamp: number;
@@ -119,6 +126,8 @@ type AgentMessage = CoreMessage & {
119
126
  responseId?: string;
120
127
  result?: GenerateTextResult<any>;
121
128
  sessionId: string;
129
+ correlationId: string;
130
+ parentCorrelationId?: string;
122
131
  };
123
132
  type AgentMessageInput = CoreMessage & {
124
133
  timestamp?: number;
@@ -128,6 +137,8 @@ type AgentMessageInput = CoreMessage & {
128
137
  * which message this message is responding to, if any.
129
138
  */
130
139
  responseId?: string;
140
+ correlationId?: string;
141
+ parentCorrelationId?: string;
131
142
  result?: GenerateTextResult<any>;
132
143
  };
133
144
  interface AgentObservation<TActor extends AnyActorRef> {
@@ -223,8 +234,8 @@ type Agent<TContext, TEvents extends EventObject> = ActorRefFrom<AgentLogic<TEve
223
234
  * - Additional `context`
224
235
  */
225
236
  decide: (options: AgentDecideOptions) => Promise<AgentPlan<TEvents> | undefined>;
226
- generateText: (options: AgentGenerateTextOptions) => Promise<GenerateTextResult<Record<string, any>>>;
227
- streamText: (options: AgentStreamTextOptions) => Promise<StreamTextResult<Record<string, CoreTool<any, any>>>>;
237
+ generateText: (options: AgentGenerateTextOptions) => Promise<AgentGenerateTextResult>;
238
+ streamText: (options: AgentStreamTextOptions) => Promise<AgentStreamTextResult>;
228
239
  addObservation: (observationInput: AgentObservationInput) => AgentObservation<any>;
229
240
  addMessage: (messageInput: AgentMessageInput) => AgentMessage;
230
241
  addFeedback: (feedbackInput: AgentFeedbackInput) => AgentFeedback;
@@ -306,16 +317,24 @@ type Agent<TContext, TEvents extends EventObject> = ActorRefFrom<AgentLogic<TEve
306
317
  interact<TActor extends AnyActorRef>(actorRef: TActor, getInput: (observation: AgentObservation<TActor>) => AgentDecisionInput | undefined): Subscription;
307
318
  };
308
319
  type AnyAgent = Agent<any, any>;
309
- type FromAgent<T> = T | ((self: AnyAgent) => T | Promise<T>);
310
- interface CommonTextOptions {
320
+ type FromAgent<T> = T | ((agent: AnyAgent) => T | Promise<T>);
321
+ type CommonTextOptions = {
311
322
  prompt: FromAgent<string>;
312
323
  model?: LanguageModel;
313
324
  context?: Record<string, any>;
314
325
  messages?: FromAgent<CoreMessage[]>;
315
326
  template?: PromptTemplate<any>;
316
- }
327
+ correlationId?: string;
328
+ parentCorrelationId?: string;
329
+ };
330
+ type TextResultMeta = {
331
+ correlationId: string;
332
+ parentCorrelationId?: string;
333
+ };
317
334
  type AgentGenerateTextOptions = Omit<GenerateTextOptions, 'model' | 'prompt' | 'messages'> & CommonTextOptions;
335
+ type AgentGenerateTextResult = GenerateTextResult<any> & TextResultMeta;
318
336
  type AgentStreamTextOptions = Omit<StreamTextOptions, 'model' | 'prompt' | 'messages'> & CommonTextOptions;
337
+ type AgentStreamTextResult = StreamTextResult<any> & TextResultMeta;
319
338
  interface ObservedState {
320
339
  /**
321
340
  * The current state value of the state machine, e.g.
@@ -406,4 +425,4 @@ declare function fromText<T extends AnyAgent>(agent: T, defaultOptions?: AgentGe
406
425
 
407
426
  declare function fromDecision(agent: AnyAgent, defaultInput?: AgentDecisionInput): AgentDecisionLogic<any>;
408
427
 
409
- export { type AIAdapter, type Agent, type AgentDecideOptions, type AgentDecisionInput, type AgentDecisionLogic, type AgentEmitted, type AgentFeedback, type AgentFeedbackInput, type AgentGenerateTextOptions, type AgentLogic, type AgentLongTermMemory, type AgentMemory, type AgentMemoryContext, type AgentMessage, type AgentMessageInput, type AgentObservation, type AgentObservationInput, type AgentPlan, type AgentPlanInput, type AgentPlanner, type AgentStreamTextOptions, type AnyAgent, type AppendOnlyStorage, type CommonTextOptions, type Compute, type ContextFromZodContextMapping, type EventsFromZodEventMapping, type FromAgent, type GenerateTextOptions, type ObservedState, type ObservedStateFrom, type PromptTemplate, type StreamTextOptions, type TransitionData, createAgent, fromDecision, fromText, fromTextStream };
428
+ export { type AIAdapter, type Agent, type AgentDecideOptions, type AgentDecisionInput, type AgentDecisionLogic, type AgentEmitted, type AgentFeedback, type AgentFeedbackInput, type AgentGenerateTextOptions, type AgentGenerateTextResult, type AgentLogic, type AgentLongTermMemory, type AgentMemory, type AgentMemoryContext, type AgentMessage, type AgentMessageInput, type AgentObservation, type AgentObservationInput, type AgentPlan, type AgentPlanInput, type AgentPlanner, type AgentStreamTextOptions, type AgentStreamTextResult, type AnyAgent, type AppendOnlyStorage, type CommonTextOptions, type Compute, type ContextFromZodContextMapping, type EventsFromZodEventMapping, type FromAgent, type GenerateTextOptions, type ObservedState, type ObservedStateFrom, type PromptTemplate, type StreamTextOptions, type TextResultMeta, type TransitionData, createAgent, fromDecision, fromText, fromTextStream };
package/dist/index.d.ts CHANGED
@@ -97,17 +97,24 @@ type AgentDecideOptions = {
97
97
  events?: ZodEventMapping;
98
98
  } & Omit<Parameters<typeof generateText>[0], 'model' | 'tools' | 'prompt' | 'messages'>;
99
99
  interface AgentFeedback {
100
- goal: string;
101
- observationId: string;
100
+ goal?: string;
101
+ observationId?: string;
102
+ /**
103
+ * The message correlation that the feedback is relevant for
104
+ */
105
+ correlationId?: string;
102
106
  attributes: Record<string, any>;
107
+ reward: number;
103
108
  timestamp: number;
104
109
  sessionId: string;
105
110
  }
106
111
  interface AgentFeedbackInput {
107
- goal: string;
108
- observationId: string;
109
- attributes: Record<string, any>;
112
+ goal?: string;
113
+ observationId?: string;
114
+ correlationId?: string;
115
+ attributes?: Record<string, any>;
110
116
  timestamp?: number;
117
+ reward?: number;
111
118
  }
112
119
  type AgentMessage = CoreMessage & {
113
120
  timestamp: number;
@@ -119,6 +126,8 @@ type AgentMessage = CoreMessage & {
119
126
  responseId?: string;
120
127
  result?: GenerateTextResult<any>;
121
128
  sessionId: string;
129
+ correlationId: string;
130
+ parentCorrelationId?: string;
122
131
  };
123
132
  type AgentMessageInput = CoreMessage & {
124
133
  timestamp?: number;
@@ -128,6 +137,8 @@ type AgentMessageInput = CoreMessage & {
128
137
  * which message this message is responding to, if any.
129
138
  */
130
139
  responseId?: string;
140
+ correlationId?: string;
141
+ parentCorrelationId?: string;
131
142
  result?: GenerateTextResult<any>;
132
143
  };
133
144
  interface AgentObservation<TActor extends AnyActorRef> {
@@ -223,8 +234,8 @@ type Agent<TContext, TEvents extends EventObject> = ActorRefFrom<AgentLogic<TEve
223
234
  * - Additional `context`
224
235
  */
225
236
  decide: (options: AgentDecideOptions) => Promise<AgentPlan<TEvents> | undefined>;
226
- generateText: (options: AgentGenerateTextOptions) => Promise<GenerateTextResult<Record<string, any>>>;
227
- streamText: (options: AgentStreamTextOptions) => Promise<StreamTextResult<Record<string, CoreTool<any, any>>>>;
237
+ generateText: (options: AgentGenerateTextOptions) => Promise<AgentGenerateTextResult>;
238
+ streamText: (options: AgentStreamTextOptions) => Promise<AgentStreamTextResult>;
228
239
  addObservation: (observationInput: AgentObservationInput) => AgentObservation<any>;
229
240
  addMessage: (messageInput: AgentMessageInput) => AgentMessage;
230
241
  addFeedback: (feedbackInput: AgentFeedbackInput) => AgentFeedback;
@@ -306,16 +317,24 @@ type Agent<TContext, TEvents extends EventObject> = ActorRefFrom<AgentLogic<TEve
306
317
  interact<TActor extends AnyActorRef>(actorRef: TActor, getInput: (observation: AgentObservation<TActor>) => AgentDecisionInput | undefined): Subscription;
307
318
  };
308
319
  type AnyAgent = Agent<any, any>;
309
- type FromAgent<T> = T | ((self: AnyAgent) => T | Promise<T>);
310
- interface CommonTextOptions {
320
+ type FromAgent<T> = T | ((agent: AnyAgent) => T | Promise<T>);
321
+ type CommonTextOptions = {
311
322
  prompt: FromAgent<string>;
312
323
  model?: LanguageModel;
313
324
  context?: Record<string, any>;
314
325
  messages?: FromAgent<CoreMessage[]>;
315
326
  template?: PromptTemplate<any>;
316
- }
327
+ correlationId?: string;
328
+ parentCorrelationId?: string;
329
+ };
330
+ type TextResultMeta = {
331
+ correlationId: string;
332
+ parentCorrelationId?: string;
333
+ };
317
334
  type AgentGenerateTextOptions = Omit<GenerateTextOptions, 'model' | 'prompt' | 'messages'> & CommonTextOptions;
335
+ type AgentGenerateTextResult = GenerateTextResult<any> & TextResultMeta;
318
336
  type AgentStreamTextOptions = Omit<StreamTextOptions, 'model' | 'prompt' | 'messages'> & CommonTextOptions;
337
+ type AgentStreamTextResult = StreamTextResult<any> & TextResultMeta;
319
338
  interface ObservedState {
320
339
  /**
321
340
  * The current state value of the state machine, e.g.
@@ -406,4 +425,4 @@ declare function fromText<T extends AnyAgent>(agent: T, defaultOptions?: AgentGe
406
425
 
407
426
  declare function fromDecision(agent: AnyAgent, defaultInput?: AgentDecisionInput): AgentDecisionLogic<any>;
408
427
 
409
- export { type AIAdapter, type Agent, type AgentDecideOptions, type AgentDecisionInput, type AgentDecisionLogic, type AgentEmitted, type AgentFeedback, type AgentFeedbackInput, type AgentGenerateTextOptions, type AgentLogic, type AgentLongTermMemory, type AgentMemory, type AgentMemoryContext, type AgentMessage, type AgentMessageInput, type AgentObservation, type AgentObservationInput, type AgentPlan, type AgentPlanInput, type AgentPlanner, type AgentStreamTextOptions, type AnyAgent, type AppendOnlyStorage, type CommonTextOptions, type Compute, type ContextFromZodContextMapping, type EventsFromZodEventMapping, type FromAgent, type GenerateTextOptions, type ObservedState, type ObservedStateFrom, type PromptTemplate, type StreamTextOptions, type TransitionData, createAgent, fromDecision, fromText, fromTextStream };
428
+ export { type AIAdapter, type Agent, type AgentDecideOptions, type AgentDecisionInput, type AgentDecisionLogic, type AgentEmitted, type AgentFeedback, type AgentFeedbackInput, type AgentGenerateTextOptions, type AgentGenerateTextResult, type AgentLogic, type AgentLongTermMemory, type AgentMemory, type AgentMemoryContext, type AgentMessage, type AgentMessageInput, type AgentObservation, type AgentObservationInput, type AgentPlan, type AgentPlanInput, type AgentPlanner, type AgentStreamTextOptions, type AgentStreamTextResult, type AnyAgent, type AppendOnlyStorage, type CommonTextOptions, type Compute, type ContextFromZodContextMapping, type EventsFromZodEventMapping, type FromAgent, type GenerateTextOptions, type ObservedState, type ObservedStateFrom, type PromptTemplate, type StreamTextOptions, type TextResultMeta, type TransitionData, createAgent, fromDecision, fromText, fromTextStream };
package/dist/index.js CHANGED
@@ -123,7 +123,8 @@ async function getMessages(agent, prompt, options) {
123
123
  async function agentGenerateText(agent, options) {
124
124
  const resolvedOptions = {
125
125
  ...agent.defaultOptions,
126
- ...options
126
+ ...options,
127
+ correlationId: options.correlationId ?? randomId()
127
128
  };
128
129
  const template = resolvedOptions.template ?? defaultTextTemplate;
129
130
  const id = randomId();
@@ -137,7 +138,9 @@ async function agentGenerateText(agent, options) {
137
138
  id,
138
139
  role: "user",
139
140
  content: promptWithContext,
140
- timestamp: Date.now()
141
+ timestamp: Date.now(),
142
+ correlationId: resolvedOptions.correlationId,
143
+ parentCorrelationId: resolvedOptions.parentCorrelationId
141
144
  });
142
145
  const result = await agent.adapter.generateText({
143
146
  ...resolvedOptions,
@@ -150,14 +153,21 @@ async function agentGenerateText(agent, options) {
150
153
  role: "assistant",
151
154
  timestamp: Date.now(),
152
155
  responseId: id,
153
- result
156
+ result,
157
+ correlationId: resolvedOptions.correlationId,
158
+ parentCorrelationId: resolvedOptions.parentCorrelationId
154
159
  });
155
- return result;
160
+ return {
161
+ ...result,
162
+ parentCorrelationId: resolvedOptions.parentCorrelationId,
163
+ correlationId: resolvedOptions.correlationId
164
+ };
156
165
  }
157
166
  async function agentStreamText(agent, options) {
158
167
  const resolvedOptions = {
159
168
  ...agent.defaultOptions,
160
- ...options
169
+ ...options,
170
+ correlationId: options.correlationId ?? randomId()
161
171
  };
162
172
  const template = resolvedOptions.template ?? defaultTextTemplate;
163
173
  const id = randomId();
@@ -171,7 +181,9 @@ async function agentStreamText(agent, options) {
171
181
  role: "user",
172
182
  content: promptWithContext,
173
183
  id,
174
- timestamp: Date.now()
184
+ timestamp: Date.now(),
185
+ correlationId: resolvedOptions.correlationId,
186
+ parentCorrelationId: resolvedOptions.parentCorrelationId
175
187
  });
176
188
  const result = await agent.adapter.streamText({
177
189
  ...resolvedOptions,
@@ -189,16 +201,24 @@ async function agentStreamText(agent, options) {
189
201
  toolResults: [],
190
202
  usage: res.usage,
191
203
  warnings: res.warnings,
192
- rawResponse: res.rawResponse
204
+ rawResponse: res.rawResponse,
205
+ roundtrips: []
206
+ // TODO: how do we get this information?
193
207
  },
194
208
  content: res.text,
195
209
  id: randomId(),
196
210
  timestamp: Date.now(),
197
- responseId: id
211
+ responseId: id,
212
+ correlationId: resolvedOptions.correlationId,
213
+ parentCorrelationId: resolvedOptions.parentCorrelationId
198
214
  });
199
215
  }
200
216
  });
201
- return result;
217
+ return {
218
+ ...result,
219
+ parentCorrelationId: resolvedOptions.parentCorrelationId,
220
+ correlationId: resolvedOptions.correlationId
221
+ };
202
222
  }
203
223
  function fromTextStream(agent, defaultOptions) {
204
224
  return (0, import_xstate.fromObservable)(({ input }) => {
@@ -309,7 +329,6 @@ async function simplePlanner(agent, input) {
309
329
  });
310
330
  const singleResult = result.toolResults[0];
311
331
  if (!singleResult) {
312
- console.log(toolMap);
313
332
  console.warn("No tool call results returned");
314
333
  return void 0;
315
334
  }
@@ -442,12 +461,12 @@ var agentLogic = (0, import_xstate3.fromTransition)(
442
461
  }
443
462
  return state;
444
463
  },
445
- {
464
+ () => ({
446
465
  feedback: [],
447
466
  messages: [],
448
467
  observations: [],
449
468
  plans: []
450
- }
469
+ })
451
470
  );
452
471
  function createAgent({
453
472
  name,
@@ -462,7 +481,6 @@ function createAgent({
462
481
  adapter = vercelAdapter,
463
482
  ...generateTextOptions
464
483
  }) {
465
- const messageHistoryListeners = [];
466
484
  const agent = (0, import_xstate3.createActor)(logic);
467
485
  agent.events = events;
468
486
  agent.model = model;
@@ -475,7 +493,7 @@ function createAgent({
475
493
  };
476
494
  agent.memory = getMemory ? getMemory(agent) : void 0;
477
495
  agent.onMessage = (callback) => {
478
- messageHistoryListeners.push((0, import_xstate3.toObserver)(callback));
496
+ agent.on("message", (ev) => callback(ev.message));
479
497
  };
480
498
  agent.decide = (opts) => {
481
499
  return agentDecide(agent, opts);
@@ -485,7 +503,8 @@ function createAgent({
485
503
  ...messageInput,
486
504
  id: messageInput.id ?? randomId(),
487
505
  timestamp: messageInput.timestamp ?? Date.now(),
488
- sessionId: agent.sessionId
506
+ sessionId: agent.sessionId,
507
+ correlationId: messageInput.correlationId ?? randomId()
489
508
  };
490
509
  agent.send({
491
510
  type: "agent.message",
@@ -499,6 +518,8 @@ function createAgent({
499
518
  agent.addFeedback = (feedbackInput) => {
500
519
  const feedback = {
501
520
  ...feedbackInput,
521
+ attributes: { ...feedbackInput.attributes },
522
+ reward: feedbackInput.reward ?? 0,
502
523
  timestamp: feedbackInput.timestamp ?? Date.now(),
503
524
  sessionId: agent.sessionId
504
525
  };
package/dist/index.mjs CHANGED
@@ -1,8 +1,7 @@
1
1
  // src/agent.ts
2
2
  import {
3
3
  createActor,
4
- fromTransition,
5
- toObserver as toObserver2
4
+ fromTransition
6
5
  } from "xstate";
7
6
 
8
7
  // src/planners/simplePlanner.ts
@@ -92,7 +91,8 @@ async function getMessages(agent, prompt, options) {
92
91
  async function agentGenerateText(agent, options) {
93
92
  const resolvedOptions = {
94
93
  ...agent.defaultOptions,
95
- ...options
94
+ ...options,
95
+ correlationId: options.correlationId ?? randomId()
96
96
  };
97
97
  const template = resolvedOptions.template ?? defaultTextTemplate;
98
98
  const id = randomId();
@@ -106,7 +106,9 @@ async function agentGenerateText(agent, options) {
106
106
  id,
107
107
  role: "user",
108
108
  content: promptWithContext,
109
- timestamp: Date.now()
109
+ timestamp: Date.now(),
110
+ correlationId: resolvedOptions.correlationId,
111
+ parentCorrelationId: resolvedOptions.parentCorrelationId
110
112
  });
111
113
  const result = await agent.adapter.generateText({
112
114
  ...resolvedOptions,
@@ -119,14 +121,21 @@ async function agentGenerateText(agent, options) {
119
121
  role: "assistant",
120
122
  timestamp: Date.now(),
121
123
  responseId: id,
122
- result
124
+ result,
125
+ correlationId: resolvedOptions.correlationId,
126
+ parentCorrelationId: resolvedOptions.parentCorrelationId
123
127
  });
124
- return result;
128
+ return {
129
+ ...result,
130
+ parentCorrelationId: resolvedOptions.parentCorrelationId,
131
+ correlationId: resolvedOptions.correlationId
132
+ };
125
133
  }
126
134
  async function agentStreamText(agent, options) {
127
135
  const resolvedOptions = {
128
136
  ...agent.defaultOptions,
129
- ...options
137
+ ...options,
138
+ correlationId: options.correlationId ?? randomId()
130
139
  };
131
140
  const template = resolvedOptions.template ?? defaultTextTemplate;
132
141
  const id = randomId();
@@ -140,7 +149,9 @@ async function agentStreamText(agent, options) {
140
149
  role: "user",
141
150
  content: promptWithContext,
142
151
  id,
143
- timestamp: Date.now()
152
+ timestamp: Date.now(),
153
+ correlationId: resolvedOptions.correlationId,
154
+ parentCorrelationId: resolvedOptions.parentCorrelationId
144
155
  });
145
156
  const result = await agent.adapter.streamText({
146
157
  ...resolvedOptions,
@@ -158,16 +169,24 @@ async function agentStreamText(agent, options) {
158
169
  toolResults: [],
159
170
  usage: res.usage,
160
171
  warnings: res.warnings,
161
- rawResponse: res.rawResponse
172
+ rawResponse: res.rawResponse,
173
+ roundtrips: []
174
+ // TODO: how do we get this information?
162
175
  },
163
176
  content: res.text,
164
177
  id: randomId(),
165
178
  timestamp: Date.now(),
166
- responseId: id
179
+ responseId: id,
180
+ correlationId: resolvedOptions.correlationId,
181
+ parentCorrelationId: resolvedOptions.parentCorrelationId
167
182
  });
168
183
  }
169
184
  });
170
- return result;
185
+ return {
186
+ ...result,
187
+ parentCorrelationId: resolvedOptions.parentCorrelationId,
188
+ correlationId: resolvedOptions.correlationId
189
+ };
171
190
  }
172
191
  function fromTextStream(agent, defaultOptions) {
173
192
  return fromObservable(({ input }) => {
@@ -278,7 +297,6 @@ async function simplePlanner(agent, input) {
278
297
  });
279
298
  const singleResult = result.toolResults[0];
280
299
  if (!singleResult) {
281
- console.log(toolMap);
282
300
  console.warn("No tool call results returned");
283
301
  return void 0;
284
302
  }
@@ -411,12 +429,12 @@ var agentLogic = fromTransition(
411
429
  }
412
430
  return state;
413
431
  },
414
- {
432
+ () => ({
415
433
  feedback: [],
416
434
  messages: [],
417
435
  observations: [],
418
436
  plans: []
419
- }
437
+ })
420
438
  );
421
439
  function createAgent({
422
440
  name,
@@ -431,7 +449,6 @@ function createAgent({
431
449
  adapter = vercelAdapter,
432
450
  ...generateTextOptions
433
451
  }) {
434
- const messageHistoryListeners = [];
435
452
  const agent = createActor(logic);
436
453
  agent.events = events;
437
454
  agent.model = model;
@@ -444,7 +461,7 @@ function createAgent({
444
461
  };
445
462
  agent.memory = getMemory ? getMemory(agent) : void 0;
446
463
  agent.onMessage = (callback) => {
447
- messageHistoryListeners.push(toObserver2(callback));
464
+ agent.on("message", (ev) => callback(ev.message));
448
465
  };
449
466
  agent.decide = (opts) => {
450
467
  return agentDecide(agent, opts);
@@ -454,7 +471,8 @@ function createAgent({
454
471
  ...messageInput,
455
472
  id: messageInput.id ?? randomId(),
456
473
  timestamp: messageInput.timestamp ?? Date.now(),
457
- sessionId: agent.sessionId
474
+ sessionId: agent.sessionId,
475
+ correlationId: messageInput.correlationId ?? randomId()
458
476
  };
459
477
  agent.send({
460
478
  type: "agent.message",
@@ -468,6 +486,8 @@ function createAgent({
468
486
  agent.addFeedback = (feedbackInput) => {
469
487
  const feedback = {
470
488
  ...feedbackInput,
489
+ attributes: { ...feedbackInput.attributes },
490
+ reward: feedbackInput.reward ?? 0,
471
491
  timestamp: feedbackInput.timestamp ?? Date.now(),
472
492
  sessionId: agent.sessionId
473
493
  };
package/package.json CHANGED
@@ -1,21 +1,10 @@
1
1
  {
2
2
  "name": "@statelyai/agent",
3
- "version": "1.0.0",
3
+ "version": "1.1.2",
4
4
  "description": "Stateful agents that make decisions based on finite-state machine models",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
8
- "scripts": {
9
- "build": "tsup src/index.ts --format cjs,esm --dts",
10
- "lint": "tsc --noEmit",
11
- "test": "vitest",
12
- "test:ci": "vitest --run",
13
- "example": "ts-node examples/helpers/runner.ts",
14
- "prepublishOnly": "tsup src/index.ts --format cjs,esm --dts",
15
- "changeset": "changeset",
16
- "release": "changeset publish",
17
- "version": "changeset version"
18
- },
19
8
  "keywords": [
20
9
  "ai",
21
10
  "state machine",
@@ -31,14 +20,14 @@
31
20
  "@langchain/community": "^0.0.53",
32
21
  "@langchain/core": "^0.1.63",
33
22
  "@langchain/openai": "^0.0.28",
34
- "@types/node": "^20.14.10",
23
+ "@types/node": "^20.14.13",
35
24
  "@types/object-hash": "^3.0.6",
36
25
  "dotenv": "^16.4.5",
37
26
  "json-schema-to-ts": "^3.1.0",
38
27
  "ts-node": "^10.9.2",
39
- "tsup": "^8.1.0",
40
- "typescript": "^5.5.3",
41
- "vitest": "^1.6.0",
28
+ "tsup": "^8.2.3",
29
+ "typescript": "^5.5.4",
30
+ "vitest": "^2.0.4",
42
31
  "wikipedia": "^2.1.2",
43
32
  "zod": "^3.23.8"
44
33
  },
@@ -46,11 +35,20 @@
46
35
  "access": "public"
47
36
  },
48
37
  "dependencies": {
49
- "@ai-sdk/openai": "^0.0.31",
38
+ "@ai-sdk/openai": "^0.0.40",
50
39
  "@xstate/graph": "^2.0.0",
51
- "ai": "^3.2.22",
40
+ "ai": "^3.2.40",
52
41
  "object-hash": "^3.0.0",
53
- "xstate": "^5.15.0"
42
+ "xstate": "^5.16.0"
54
43
  },
55
- "packageManager": "pnpm@8.11.0"
56
- }
44
+ "scripts": {
45
+ "build": "tsup src/index.ts --format cjs,esm --dts",
46
+ "lint": "tsc --noEmit",
47
+ "test": "vitest",
48
+ "test:ci": "vitest --run",
49
+ "example": "ts-node examples/helpers/runner.ts",
50
+ "changeset": "changeset",
51
+ "release": "changeset publish",
52
+ "version": "changeset version"
53
+ }
54
+ }
package/readme.md CHANGED
@@ -1,8 +1,5 @@
1
1
  # Stately Agent
2
2
 
3
- > [!WARNING]
4
- > Alpha software! Not ready for production yet.
5
-
6
3
  Stately Agent is a flexible framework for building AI agents using state machines. Stately agents go beyond normal LLM-based AI agents by:
7
4
 
8
5
  - Using state machines to guide the agent's behavior, powered by [XState](https://stately.ai/docs/xstate)
@@ -10,4 +7,4 @@ Stately Agent is a flexible framework for building AI agents using state machine
10
7
  - Enabling custom **planning** abilities for agents to achieve specific goals based on state machine logic, observations, and feedback
11
8
  - Wrapping the [Vercel AI SDK](https://sdk.vercel.ai/) to easily support multiple model providers, such as OpenAI, Anthropic, Google, Mistral, Groq, Perplexity, and more
12
9
 
13
- _Documentation coming soon_
10
+ **Read the documentation: [stately.ai/docs/agents](https://stately.ai/docs/agents)**
package/src/agent.test.ts CHANGED
@@ -1,5 +1,10 @@
1
1
  import { test, expect, vi } from 'vitest';
2
- import { createAgent, type AIAdapter } from './';
2
+ import {
3
+ AgentGenerateTextResult,
4
+ AgentMessage,
5
+ createAgent,
6
+ type AIAdapter,
7
+ } from './';
3
8
  import { createActor, createMachine } from 'xstate';
4
9
  import { GenerateTextResult } from 'ai';
5
10
  import { z } from 'zod';
@@ -297,7 +302,7 @@ test('You can listen for plan events', async () => {
297
302
  },
298
303
  },
299
304
  ],
300
- } as any as GenerateTextResult<any>;
305
+ } as any as AgentGenerateTextResult;
301
306
  },
302
307
  streamText: {} as any,
303
308
  },
@@ -357,3 +362,145 @@ test('agent.types provides context and event types', () => {
357
362
  // @ts-expect-error
358
363
  agent.types.context satisfies { score: string };
359
364
  });
365
+
366
+ test.each(['generateText', 'streamText'] as const)(
367
+ 'can provide a correlation ID (%s)',
368
+ async (method) => {
369
+ const agent = createAgent({
370
+ model: {} as any,
371
+ events: {},
372
+ adapter: {
373
+ [method]: async (opts: any) => {
374
+ const res = {
375
+ text: 'response',
376
+ };
377
+
378
+ opts.onFinish?.(res);
379
+
380
+ return res as AgentGenerateTextResult;
381
+ },
382
+ } as any as AIAdapter,
383
+ });
384
+
385
+ const promise = new Promise<AgentMessage>((res) => {
386
+ agent.onMessage((msg) => {
387
+ if (msg.role === 'assistant') {
388
+ res(msg);
389
+ }
390
+ });
391
+ });
392
+
393
+ await agent[method]({
394
+ prompt: 'hi',
395
+ correlationId: 'c-1',
396
+ });
397
+
398
+ const msg = await promise;
399
+
400
+ expect(msg.correlationId).toBe('c-1');
401
+ expect(msg.parentCorrelationId).toBe(undefined);
402
+ }
403
+ );
404
+
405
+ test.each(['generateText', 'streamText'] as const)(
406
+ 'correlation IDs are automatically generated if not provided (%s)',
407
+ async (method) => {
408
+ const agent = createAgent({
409
+ model: {} as any,
410
+ events: {},
411
+ adapter: {
412
+ [method]: async (opts: any) => {
413
+ const res = {
414
+ text: 'response',
415
+ };
416
+
417
+ opts.onFinish?.(res);
418
+
419
+ return res as AgentGenerateTextResult;
420
+ },
421
+ } as any as AIAdapter,
422
+ });
423
+
424
+ await agent[method]({
425
+ prompt: 'hi',
426
+ });
427
+
428
+ const messages = agent.getMessages();
429
+
430
+ expect(messages[0]?.correlationId).toEqual(expect.stringMatching(/.+/));
431
+ expect(messages[0]?.role).toBe('user');
432
+ expect(messages[1]?.correlationId).toEqual(expect.stringMatching(/.+/));
433
+ expect(messages[1]?.role).toBe('assistant');
434
+
435
+ expect(messages[0]!.correlationId).toEqual(messages[1]!.correlationId);
436
+ }
437
+ );
438
+
439
+ test.each(['generateText', 'streamText'] as const)(
440
+ 'can provide a parent correlation ID (%s)',
441
+ async (method) => {
442
+ const agent = createAgent({
443
+ model: {} as any,
444
+ events: {},
445
+ adapter: {
446
+ [method]: async (opts: any) => {
447
+ const res = {
448
+ text: 'response',
449
+ };
450
+
451
+ opts.onFinish?.(res);
452
+
453
+ return res as AgentGenerateTextResult;
454
+ },
455
+ } as any as AIAdapter,
456
+ });
457
+
458
+ await agent[method]({
459
+ prompt: 'hi',
460
+ correlationId: 'c-1',
461
+ parentCorrelationId: 'c-0',
462
+ });
463
+
464
+ const msg = agent.getMessages().find((msg) => msg.role === 'assistant')!;
465
+
466
+ expect(msg.correlationId).toBe('c-1');
467
+ expect(msg.parentCorrelationId).toBe('c-0');
468
+ }
469
+ );
470
+
471
+ test.each(['generateText', 'streamText'] as const)(
472
+ 'can add feedback to a correlation (%s)',
473
+ async (method) => {
474
+ const agent = createAgent({
475
+ name: 'test',
476
+ model: {} as any,
477
+ events: {},
478
+ adapter: {
479
+ [method]: async (opts: any) => {
480
+ const res = {
481
+ text: 'response',
482
+ };
483
+
484
+ opts.onFinish?.(res);
485
+
486
+ return res as AgentGenerateTextResult;
487
+ },
488
+ } as any as AIAdapter,
489
+ });
490
+
491
+ const res = await agent[method]({
492
+ prompt: 'test',
493
+ });
494
+
495
+ agent.addFeedback({
496
+ correlationId: res.correlationId,
497
+ reward: -1,
498
+ });
499
+
500
+ const message = agent.getMessages()[0]!;
501
+ const feedback = agent.getFeedback()[0]!;
502
+
503
+ expect(message.correlationId).toBeDefined();
504
+ expect(feedback.correlationId).toEqual(message.correlationId);
505
+ }
506
+ );
package/src/agent.ts CHANGED
@@ -22,6 +22,7 @@ import {
22
22
  AgentMemoryContext,
23
23
  AgentObservation,
24
24
  ContextFromZodContextMapping,
25
+ AgentFeedback,
25
26
  } from './types';
26
27
  import { simplePlanner } from './planners/simplePlanner';
27
28
  import { agentGenerateText, agentStreamText } from './text';
@@ -73,12 +74,13 @@ export const agentLogic: AgentLogic<AnyEventObject> = fromTransition(
73
74
  }
74
75
  return state;
75
76
  },
76
- {
77
- feedback: [],
78
- messages: [],
79
- observations: [],
80
- plans: [],
81
- } as AgentMemoryContext
77
+ () =>
78
+ ({
79
+ feedback: [],
80
+ messages: [],
81
+ observations: [],
82
+ plans: [],
83
+ } as AgentMemoryContext)
82
84
  );
83
85
 
84
86
  export function createAgent<
@@ -140,8 +142,6 @@ export function createAgent<
140
142
  logic?: AgentLogic<TEvents>;
141
143
  adapter?: AIAdapter;
142
144
  } & GenerateTextOptions): Agent<TContext, TEvents> {
143
- const messageHistoryListeners: Observer<AgentMessage>[] = [];
144
-
145
145
  const agent = createActor(logic) as unknown as Agent<TContext, TEvents>;
146
146
  agent.events = events;
147
147
  agent.model = model;
@@ -155,7 +155,7 @@ export function createAgent<
155
155
  agent.memory = getMemory ? getMemory(agent) : undefined;
156
156
 
157
157
  agent.onMessage = (callback) => {
158
- messageHistoryListeners.push(toObserver(callback));
158
+ agent.on('message', (ev) => callback(ev.message));
159
159
  };
160
160
 
161
161
  agent.decide = (opts) => {
@@ -168,7 +168,8 @@ export function createAgent<
168
168
  id: messageInput.id ?? randomId(),
169
169
  timestamp: messageInput.timestamp ?? Date.now(),
170
170
  sessionId: agent.sessionId,
171
- };
171
+ correlationId: messageInput.correlationId ?? randomId(),
172
+ } satisfies AgentMessage;
172
173
  agent.send({
173
174
  type: 'agent.message',
174
175
  message,
@@ -185,9 +186,11 @@ export function createAgent<
185
186
  agent.addFeedback = (feedbackInput) => {
186
187
  const feedback = {
187
188
  ...feedbackInput,
189
+ attributes: { ...feedbackInput.attributes },
190
+ reward: feedbackInput.reward ?? 0,
188
191
  timestamp: feedbackInput.timestamp ?? Date.now(),
189
192
  sessionId: agent.sessionId,
190
- };
193
+ } satisfies AgentFeedback;
191
194
  agent.send({
192
195
  type: 'agent.feedback',
193
196
  feedback,
@@ -1,4 +1,4 @@
1
- import { CoreTool, tool } from 'ai';
1
+ import { type CoreTool, tool } from 'ai';
2
2
  import {
3
3
  AgentPlan,
4
4
  AgentPlanInput,
@@ -118,7 +118,6 @@ export async function simplePlanner<T extends AnyAgent>(
118
118
  const singleResult = result.toolResults[0];
119
119
 
120
120
  if (!singleResult) {
121
- console.log(toolMap);
122
121
  // TODO: retries?
123
122
  console.warn('No tool call results returned');
124
123
  return undefined;
package/src/text.ts CHANGED
@@ -1,12 +1,9 @@
1
- import type {
2
- CoreMessage,
3
- CoreTool,
4
- GenerateTextResult,
5
- StreamTextResult,
6
- } from 'ai';
1
+ import type { CoreMessage, CoreTool, GenerateTextResult } from 'ai';
7
2
  import {
8
3
  AgentGenerateTextOptions,
4
+ AgentGenerateTextResult,
9
5
  AgentStreamTextOptions,
6
+ AgentStreamTextResult,
10
7
  AnyAgent,
11
8
  } from './types';
12
9
  import { defaultTextTemplate } from './templates/defaultText';
@@ -51,11 +48,13 @@ export async function getMessages(
51
48
  export async function agentGenerateText<T extends AnyAgent>(
52
49
  agent: T,
53
50
  options: AgentGenerateTextOptions
54
- ) {
51
+ ): Promise<AgentGenerateTextResult> {
55
52
  const resolvedOptions = {
56
53
  ...agent.defaultOptions,
57
54
  ...options,
55
+ correlationId: options.correlationId ?? randomId(),
58
56
  };
57
+ // Generate a correlation ID if one is not provided
59
58
  const template = resolvedOptions.template ?? defaultTextTemplate;
60
59
  // TODO: check if messages was provided instead
61
60
  const id = randomId();
@@ -76,6 +75,8 @@ export async function agentGenerateText<T extends AnyAgent>(
76
75
  role: 'user',
77
76
  content: promptWithContext,
78
77
  timestamp: Date.now(),
78
+ correlationId: resolvedOptions.correlationId,
79
+ parentCorrelationId: resolvedOptions.parentCorrelationId,
79
80
  });
80
81
 
81
82
  const result = await agent.adapter.generateText({
@@ -91,18 +92,25 @@ export async function agentGenerateText<T extends AnyAgent>(
91
92
  timestamp: Date.now(),
92
93
  responseId: id,
93
94
  result,
95
+ correlationId: resolvedOptions.correlationId,
96
+ parentCorrelationId: resolvedOptions.parentCorrelationId,
94
97
  });
95
98
 
96
- return result;
99
+ return {
100
+ ...result,
101
+ parentCorrelationId: resolvedOptions.parentCorrelationId,
102
+ correlationId: resolvedOptions.correlationId,
103
+ };
97
104
  }
98
105
 
99
106
  export async function agentStreamText(
100
107
  agent: AnyAgent,
101
108
  options: AgentStreamTextOptions
102
- ): Promise<StreamTextResult<any>> {
109
+ ): Promise<AgentStreamTextResult> {
103
110
  const resolvedOptions = {
104
111
  ...agent.defaultOptions,
105
112
  ...options,
113
+ correlationId: options.correlationId ?? randomId(),
106
114
  };
107
115
  const template = resolvedOptions.template ?? defaultTextTemplate;
108
116
 
@@ -124,6 +132,8 @@ export async function agentStreamText(
124
132
  content: promptWithContext,
125
133
  id,
126
134
  timestamp: Date.now(),
135
+ correlationId: resolvedOptions.correlationId,
136
+ parentCorrelationId: resolvedOptions.parentCorrelationId,
127
137
  });
128
138
 
129
139
  const result = await agent.adapter.streamText({
@@ -143,16 +153,23 @@ export async function agentStreamText(
143
153
  usage: res.usage,
144
154
  warnings: res.warnings,
145
155
  rawResponse: res.rawResponse,
156
+ roundtrips: [], // TODO: how do we get this information?
146
157
  },
147
158
  content: res.text,
148
159
  id: randomId(),
149
160
  timestamp: Date.now(),
150
161
  responseId: id,
162
+ correlationId: resolvedOptions.correlationId,
163
+ parentCorrelationId: resolvedOptions.parentCorrelationId,
151
164
  });
152
165
  },
153
166
  });
154
167
 
155
- return result;
168
+ return {
169
+ ...result,
170
+ parentCorrelationId: resolvedOptions.parentCorrelationId,
171
+ correlationId: resolvedOptions.correlationId,
172
+ } as unknown as AgentStreamTextResult; // TODO: fix
156
173
  }
157
174
 
158
175
  export function fromTextStream<T extends AnyAgent>(
package/src/types.ts CHANGED
@@ -128,18 +128,25 @@ export type AgentDecideOptions = {
128
128
  >;
129
129
 
130
130
  export interface AgentFeedback {
131
- goal: string;
132
- observationId: string;
131
+ goal?: string;
132
+ observationId?: string;
133
+ /**
134
+ * The message correlation that the feedback is relevant for
135
+ */
136
+ correlationId?: string;
133
137
  attributes: Record<string, any>;
138
+ reward: number;
134
139
  timestamp: number;
135
140
  sessionId: string;
136
141
  }
137
142
 
138
143
  export interface AgentFeedbackInput {
139
- goal: string;
140
- observationId: string; // Observation ID;
141
- attributes: Record<string, any>;
144
+ goal?: string;
145
+ observationId?: string;
146
+ correlationId?: string;
147
+ attributes?: Record<string, any>;
142
148
  timestamp?: number;
149
+ reward?: number;
143
150
  }
144
151
 
145
152
  export type AgentMessage = CoreMessage & {
@@ -152,6 +159,8 @@ export type AgentMessage = CoreMessage & {
152
159
  responseId?: string;
153
160
  result?: GenerateTextResult<any>;
154
161
  sessionId: string;
162
+ correlationId: string;
163
+ parentCorrelationId?: string;
155
164
  };
156
165
 
157
166
  export type AgentMessageInput = CoreMessage & {
@@ -162,6 +171,8 @@ export type AgentMessageInput = CoreMessage & {
162
171
  * which message this message is responding to, if any.
163
172
  */
164
173
  responseId?: string;
174
+ correlationId?: string;
175
+ parentCorrelationId?: string;
165
176
  result?: GenerateTextResult<any>;
166
177
  };
167
178
 
@@ -293,12 +304,12 @@ export type Agent<TContext, TEvents extends EventObject> = ActorRefFrom<
293
304
  // Generate text
294
305
  generateText: (
295
306
  options: AgentGenerateTextOptions
296
- ) => Promise<GenerateTextResult<Record<string, any>>>;
307
+ ) => Promise<AgentGenerateTextResult>;
297
308
 
298
309
  // Stream text
299
310
  streamText: (
300
311
  options: AgentStreamTextOptions
301
- ) => Promise<StreamTextResult<Record<string, CoreTool<any, any>>>>;
312
+ ) => Promise<AgentStreamTextResult>;
302
313
 
303
314
  addObservation: (
304
315
  observationInput: AgentObservationInput
@@ -395,15 +406,22 @@ export type Agent<TContext, TEvents extends EventObject> = ActorRefFrom<
395
406
 
396
407
  export type AnyAgent = Agent<any, any>;
397
408
 
398
- export type FromAgent<T> = T | ((self: AnyAgent) => T | Promise<T>);
409
+ export type FromAgent<T> = T | ((agent: AnyAgent) => T | Promise<T>);
399
410
 
400
- export interface CommonTextOptions {
411
+ export type CommonTextOptions = {
401
412
  prompt: FromAgent<string>;
402
413
  model?: LanguageModel;
403
414
  context?: Record<string, any>;
404
415
  messages?: FromAgent<CoreMessage[]>;
405
416
  template?: PromptTemplate<any>;
406
- }
417
+ correlationId?: string;
418
+ parentCorrelationId?: string;
419
+ };
420
+
421
+ export type TextResultMeta = {
422
+ correlationId: string;
423
+ parentCorrelationId?: string;
424
+ };
407
425
 
408
426
  export type AgentGenerateTextOptions = Omit<
409
427
  GenerateTextOptions,
@@ -411,12 +429,16 @@ export type AgentGenerateTextOptions = Omit<
411
429
  > &
412
430
  CommonTextOptions;
413
431
 
432
+ export type AgentGenerateTextResult = GenerateTextResult<any> & TextResultMeta;
433
+
414
434
  export type AgentStreamTextOptions = Omit<
415
435
  StreamTextOptions,
416
436
  'model' | 'prompt' | 'messages'
417
437
  > &
418
438
  CommonTextOptions;
419
439
 
440
+ export type AgentStreamTextResult = StreamTextResult<any> & TextResultMeta;
441
+
420
442
  export interface ObservedState {
421
443
  /**
422
444
  * The current state value of the state machine, e.g.
@@ -1,12 +0,0 @@
1
- ---
2
- '@statelyai/agent': minor
3
- ---
4
-
5
- Added four new methods for easily retrieving agent messages, observations, feedback, and plans:
6
-
7
- - `agent.getMessages()`
8
- - `agent.getObservations()`
9
- - `agent.getFeedback()`
10
- - `agent.getPlans()`
11
-
12
- The `agent.select(…)` method is deprecated in favor of these methods.
@@ -1,5 +0,0 @@
1
- ---
2
- "@statelyai/agent": patch
3
- ---
4
-
5
- Use nanoid
@@ -1,5 +0,0 @@
1
- ---
2
- '@statelyai/agent': patch
3
- ---
4
-
5
- Messages are now properly included in `agent.decide(…)`, when specified.
@@ -1,26 +0,0 @@
1
- ---
2
- '@statelyai/agent': minor
3
- ---
4
-
5
- You can now add `context` Zod schema to your agent. For now, this is meant to be passed directly to the state machine, but in the future, the schema can be shared with the LLM agent to better understand the state machine and its context for decision making.
6
-
7
- Breaking: The `context` and `events` types are now in `agent.types` instead of ~~`agent.eventTypes`.
8
-
9
- ```ts
10
- const agent = createAgent({
11
- // ...
12
- context: {
13
- score: z.number().describe('The score of the game'),
14
- // ...
15
- },
16
- });
17
-
18
- const machine = setup({
19
- types: agent.types,
20
- }).createMachine({
21
- context: {
22
- score: 0,
23
- },
24
- // ...
25
- });
26
- ```