diff --git a/packages/framework/src/agent.ts b/packages/framework/src/agent.ts
index 7397bbb..df84709 100644
--- a/packages/framework/src/agent.ts
+++ b/packages/framework/src/agent.ts
@@ -3,7 +3,7 @@ import { zodFunction, zodResponseFormat } from 'openai/helpers/zod.js'
import { z } from 'zod'
import { openai, Provider } from './models.js'
-import { finish, WorkflowState } from './state.js'
+import { finish, request, response, WorkflowState } from './state.js'
import { Tool } from './tool.js'
import { Message } from './types.js'
import { Workflow } from './workflow.js'
@@ -39,7 +39,7 @@ export const agent = (options: AgentOptions = {}): Agent => {
)
: []
- const response = await provider.completions({
+ const res = await provider.completions({
messages: [
{
role: 'system',
@@ -56,18 +56,9 @@ export const agent = (options: AgentOptions = {}): Agent => {
Try to complete the task on your own.
`,
},
- {
- role: 'assistant',
- content: 'What have been done so far?',
- },
- {
- role: 'user',
- content: `Here is all the work done so far by other agents: ${JSON.stringify(context)}`,
- },
- {
- role: 'assistant',
- content: 'What do you want me to do now?',
- },
+ response('What have been done so far?'),
+ request(`Here is all the work done so far by other agents: ${JSON.stringify(context)}`),
+ response('What do you want me to do now?'),
...state.messages,
],
tools: mappedTools.length > 0 ? mappedTools : undefined,
@@ -94,40 +85,30 @@ export const agent = (options: AgentOptions = {}): Agent => {
),
})
- if (response.choices[0].message.tool_calls.length > 0) {
+ if (res.choices[0].message.tool_calls.length > 0) {
return {
...state,
status: 'paused',
- messages: state.messages.concat(response.choices[0].message),
+ messages: state.messages.concat(res.choices[0].message),
}
}
- const result = response.choices[0].message.parsed
- if (!result) {
+ const message = res.choices[0].message.parsed
+ if (!message) {
throw new Error('No parsed response received')
}
- if (result.response.kind === 'error') {
- throw new Error(result.response.reasoning)
+ if (message.response.kind === 'error') {
+ throw new Error(message.response.reasoning)
}
- const agentResponse = {
- role: 'assistant' as const,
- content: result.response.result,
- }
+ const agentResponse = response(message.response.result)
- if (result.response.nextStep) {
+ if (message.response.nextStep) {
return {
...state,
status: 'running',
- messages: [
- ...state.messages,
- agentResponse,
- {
- role: 'user',
- content: result.response.nextStep,
- },
- ],
+ messages: [...state.messages, agentResponse, request(message.response.nextStep)],
}
}
diff --git a/packages/framework/src/agents/final_boss.ts b/packages/framework/src/agents/final_boss.ts
index b9ea6d8..5c87a72 100644
--- a/packages/framework/src/agents/final_boss.ts
+++ b/packages/framework/src/agents/final_boss.ts
@@ -3,11 +3,11 @@ import { zodResponseFormat } from 'openai/helpers/zod'
import { z } from 'zod'
import { agent, AgentOptions } from '../agent.js'
-import { finish } from '../state.js'
+import { finish, request, response } from '../state.js'
const defaults: AgentOptions = {
run: async (state, context, workflow) => {
- const response = await workflow.team[state.agent].provider.completions({
+ const res = await workflow.team[state.agent].provider.completions({
messages: [
{
role: 'system',
@@ -16,13 +16,10 @@ const defaults: AgentOptions = {
`,
},
...context,
- {
- role: 'user',
- content: s`
- Please summarize all executed steps and do your best to achieve
- the main goal while responding with the final answer
- `,
- },
+ request(s`
+ Please summarize all executed steps and do your best to achieve
+ the main goal while responding with the final answer
+ `),
],
response_format: zodResponseFormat(
z.object({
@@ -31,11 +28,11 @@ const defaults: AgentOptions = {
'task_result'
),
})
- const result = response.choices[0].message.parsed
- if (!result) {
+ const message = res.choices[0].message.parsed
+ if (!message) {
throw new Error('No parsed response received')
}
- return finish(state, { role: 'assistant', content: result.finalAnswer })
+ return finish(state, response(message.finalAnswer))
},
}
diff --git a/packages/framework/src/agents/resource_planner.ts b/packages/framework/src/agents/resource_planner.ts
index 9f6c017..5fd4652 100644
--- a/packages/framework/src/agents/resource_planner.ts
+++ b/packages/framework/src/agents/resource_planner.ts
@@ -3,11 +3,11 @@ import { zodResponseFormat } from 'openai/helpers/zod'
import { z } from 'zod'
import { agent, AgentOptions } from '../agent.js'
-import { handoff } from '../state.js'
+import { handoff, request, response } from '../state.js'
const defaults: AgentOptions = {
run: async (state, context, workflow) => {
- const response = await workflow.team[state.agent].provider.completions({
+ const res = await workflow.team[state.agent].provider.completions({
messages: [
{
role: 'system',
@@ -22,21 +22,14 @@ const defaults: AgentOptions = {
4. Previous task context if available
`,
},
- {
- role: 'user',
- content: s`
+ request(s`
Here are the available agents:
${Object.entries(workflow.team).map(([name, agent]) =>
agent.description ? `${agent.description}` : ''
)}
-
- `,
- },
- {
- role: 'assistant',
- content: 'What is the task?',
- },
+ `),
+ response('What is the task?'),
...state.messages,
],
temperature: 0.1,
@@ -49,12 +42,12 @@ const defaults: AgentOptions = {
),
})
- const content = response.choices[0].message.parsed
- if (!content) {
+ const message = res.choices[0].message.parsed
+ if (!message) {
throw new Error('No content in response')
}
- return handoff(state, content.agent, state.messages)
+ return handoff(state, message.agent, state.messages)
},
}
diff --git a/packages/framework/src/agents/supervisor.ts b/packages/framework/src/agents/supervisor.ts
index 52c392d..98b1cc1 100644
--- a/packages/framework/src/agents/supervisor.ts
+++ b/packages/framework/src/agents/supervisor.ts
@@ -4,13 +4,13 @@ import { z } from 'zod'
import { agent, AgentOptions } from '../agent.js'
import { getSteps } from '../messages.js'
-import { delegate } from '../state.js'
+import { delegate, request, response } from '../state.js'
const defaults: AgentOptions = {
run: async (state, context, workflow) => {
- const [request, ...messages] = state.messages
+ const [workflowRequest, ...messages] = state.messages
- const response = await workflow.team[state.agent].provider.completions({
+ const res = await workflow.team[state.agent].provider.completions({
messages: [
{
role: 'system',
@@ -28,15 +28,9 @@ const defaults: AgentOptions = {
5. Use context from completed tasks to inform next steps
`,
},
- {
- role: 'assistant',
- content: 'What is the request?',
- },
- request,
- {
- role: 'assistant',
- content: 'What has been completed so far?',
- },
+ response('What is the request?'),
+ workflowRequest,
+ response('What has been completed so far?'),
...getSteps(messages),
],
temperature: 0.2,
@@ -56,7 +50,7 @@ const defaults: AgentOptions = {
})
try {
- const content = response.choices[0].message.parsed
+ const content = res.choices[0].message.parsed
if (!content) {
throw new Error('No content in response')
}
@@ -70,13 +64,7 @@ const defaults: AgentOptions = {
return delegate(
state,
- content.tasks.map((item) => [
- 'resourcePlanner',
- {
- role: 'user',
- content: item.task,
- },
- ])
+ content.tasks.map((item) => ['resourcePlanner', request(item.task)])
)
} catch (error) {
throw new Error('Failed to determine next task')
diff --git a/packages/framework/src/iterate.ts b/packages/framework/src/iterate.ts
index 510108f..5fa1c3d 100644
--- a/packages/framework/src/iterate.ts
+++ b/packages/framework/src/iterate.ts
@@ -1,4 +1,4 @@
-import { childState, finish, WorkflowState } from './state.js'
+import { childState, finish, response, WorkflowState } from './state.js'
import { runTools } from './tool_calls.js'
import { Message } from './types.js'
import { Workflow } from './workflow.js'
@@ -48,10 +48,7 @@ export async function run(
try {
return agent.run(state, context, workflow)
} catch (error) {
- return finish(state, {
- role: 'assistant',
- content: error instanceof Error ? error.message : 'Unknown error',
- })
+ return finish(state, response(error instanceof Error ? error.message : 'Unknown error'))
}
}
diff --git a/packages/framework/src/state.ts b/packages/framework/src/state.ts
index e75d466..214bf1f 100644
--- a/packages/framework/src/state.ts
+++ b/packages/framework/src/state.ts
@@ -25,14 +25,11 @@ export const rootState = (workflow: Workflow): WorkflowState =>
childState({
agent: 'supervisor',
messages: [
- {
- role: 'user',
- content: s`
- Here is description of my workflow and expected output:
- ${workflow.description}
-
- `,
- },
+ request(s`
+ Here is description of my workflow and expected output:
+ ${workflow.description}
+
+ `),
],
})
@@ -73,3 +70,17 @@ export const handoff = (
messages,
})
}
+
+export const response = (content: string): Message => {
+ return {
+ role: 'assistant',
+ content,
+ }
+}
+
+export const request = (content: string): Message => {
+ return {
+ role: 'user',
+ content,
+ }
+}