Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
9fa1f8b
start point for datasets with the langsmith package
0xhijo Oct 13, 2025
18516bb
first version capable of taking an datasets from our project and crea…
0xhijo Oct 14, 2025
a81e77e
move agents stroage init to agent to get he possibilities to create a…
0xhijo Oct 14, 2025
68ccd0d
version with model_provider changed everywhere + remove of promot_id
0xhijo Oct 14, 2025
edaa271
working version just there is no all the examples during the run and …
0xhijo Oct 14, 2025
ae90668
version working
0xhijo Oct 14, 2025
f76d52c
version working
0xhijo Oct 14, 2025
b3f9fe9
version working with updated csv and the print log
0xhijo Oct 14, 2025
2690497
version working for with nodes confined for specialist
0xhijo Oct 15, 2025
bccc583
clean csv files
0xhijo Oct 17, 2025
f2f0210
version working with csfiles in langsmith format
0xhijo Oct 17, 2025
4c4a2c6
version before go to 1.0 version
0xhijo Oct 20, 2025
a8ca325
updated prompt
0xhijo Oct 20, 2025
57dae4c
version working with the agentConfiguration and message_ask_user
0xhijo Oct 20, 2025
50b9fa6
update the way that we use the graph node in datasets to get a better…
0xhijo Oct 21, 2025
80a11ca
prettier + add all csv
0xhijo Oct 21, 2025
a69f2b3
add the csv header'
0xhijo Oct 21, 2025
c868d7f
merge main
0xhijo Oct 21, 2025
834162d
update some fix:
0xhijo Oct 21, 2025
461aacc
working version just needs to update some data from the datasets
0xhijo Oct 21, 2025
1220796
version working
0xhijo Oct 21, 2025
90a2690
version with agent selection + payload only work for one agent
0xhijo Oct 21, 2025
79b8437
remvoed all console.log()
0xhijo Oct 21, 2025
5c94a66
updated prompt
0xhijo Oct 21, 2025
631bd85
change every console.log into logger
0xhijo Oct 21, 2025
eb317a3
version with id + name + query of the execute handoff
0xhijo Oct 22, 2025
a346fe3
version with the tools enhanced
0xhijo Oct 22, 2025
81a6298
better
0xhijo Oct 22, 2025
d48fcbc
version with constant reloacted
0xhijo Oct 22, 2025
f1c624e
version working
0xhijo Oct 24, 2025
6b396be
memory thread_id field updated
0xhijo Oct 24, 2025
4d57b9d
verify if exist
0xhijo Oct 24, 2025
ba3da67
prettier version
0xhijo Oct 27, 2025
3ce3058
version for merge
0xhijo Oct 27, 2025
12fcdc6
fix quries rag
0xhijo Oct 27, 2025
783a6da
prettier all
0xhijo Oct 27, 2025
bb6cf6f
updated readme
0xhijo Oct 27, 2025
c419dae
version with supervisor
0xhijo Oct 28, 2025
0388c89
update logger
0xhijo Oct 28, 2025
b79f27f
checkpoint
0xhijo Oct 28, 2025
eafd2d6
checkpoint
0xhijo Oct 28, 2025
63c965f
version working with the front-end
0xhijo Oct 30, 2025
744ac0a
pretteir versiion
0xhijo Oct 30, 2025
791ea7c
add await
0xhijo Oct 30, 2025
c9751d4
merge
0xhijo Oct 30, 2025
23f350f
working version
0xhijo Oct 30, 2025
5725211
pretteir
0xhijo Oct 30, 2025
9bef418
fi thread_Id ambiheous
0xhijo Oct 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion config/guards/default.guards.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
"max_profile_length": 255
},
"agents": {
"prompts_id_max_length": 255,
"profile": {
"name_max_length": 100,
"name_min_length": 3,
Expand Down
8 changes: 8 additions & 0 deletions datasets/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Ignore all CSV files except the example
*.dataset.csv
!example-dataset.dataset.csv
!supervisor-supervisor.dataset.csv
!supervisor-agentConfigurationHelper.dataset.csv
!supervisor-mcpConfigurationHelper.dataset.csv
!supervisor-snakRagAgentHelper.dataset.csv
!supervisor-agentSelectorHelper.dataset.csv
11 changes: 11 additions & 0 deletions datasets/supervisor-agentConfigurationHelper.dataset.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
messages,output_direction,dataset_split,operation_type,difficulty
"[{""role"":""user"",""content"":""can you create an agent""}]","Ask for agent purpose using message_ask_user","[""training""]","[""create_agent""]","[""very-easy""]"
"[{""role"":""user"",""content"":""can you create a websearch agent""}]","Ask to specify websearch agent purpose using message_ask_user","[""training""]","[""create_agent""]","[""very-easy""]"
"[{""role"":""user"",""content"":""can you create a websearch agent specialized in retrieving guitar information""}]","Create agent using create_agent tool","[""training""]","[""create_agent""]","[""easy""]"
"[{""role"":""user"",""content"":""can you create an agent""},{""role"":""assistant"",""content"":""What is the purpose of the agent you want to create?""},{""role"":""user"",""content"":""an agent specialized in websearch""}]","Ask for specific websearch purpose using message_ask_user","[""training""]","[""create_agent""]","[""easy""]"
"[{""role"":""user"",""content"":""can you create a websearch agent""},{""role"":""assistant"",""content"":""What is the purpose of your websearch agent?""},{""role"":""user"",""content"":""an agent specialized in finding weather for a given city""}]","Create agent using create_agent tool","[""validation""]","[""create_agent""]","[""medium""]"
"[{""role"":""user"",""content"":""i want to update my agent GuitarFindingAgent""}]","Ask what they want to modify using message_ask_user","[""training""]","[""update_agent""]","[""very-easy""]"
"[{""role"":""user"",""content"":""i want to increase the memory of my agent TradingShortExtended""}]","Use read_agent tool on TradingShortExtended","[""training""]","[""update_agent""]","[""easy""]"
"[{""role"":""user"",""content"":""i want to increase the memory of my agent TradingShortExtended""},{""role"":""tool"",""name"":""read_agent"",""content"":""Error: No agent found with name TradingShortExtended"",""tool_call_id"":""call_1""}]","Use list_agents tool to show available agents","[""validation""]","[""update_agent""]","[""medium""]"
"[{""role"":""user"",""content"":""can you delete an agent""}]","Use list_agents tool","[""training""]","[""delete_agent""]","[""very-easy""]"
"[{""role"":""user"",""content"":""can you delete agent PokemonTrainer""}]","Ask for deletion confirmation using message_ask_user","[""training""]","[""delete_agent""]","[""easy""]"
1 change: 1 addition & 0 deletions datasets/supervisor-agentSelectorHelper.dataset.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
messages,output_direction,dataset_split,operation_type,difficulty
1 change: 1 addition & 0 deletions datasets/supervisor-mcpConfigurationHelper.dataset.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
messages,output_direction,dataset_split,operation_type,difficulty
1 change: 1 addition & 0 deletions datasets/supervisor-snakRagAgentHelper.dataset.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
messages,output_direction,dataset_split,operation_type,difficulty
18 changes: 18 additions & 0 deletions datasets/supervisor-supervisor.dataset.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
messages,output_direction,dataset_split,operation_type,difficulty
"[{""role"":""user"",""content"":""can you create an agent config""}]","The agent should transfer_to_agentconfigurationhelper","[""training""]","[""transfer_to_agentconfigurationhelper""]","[""very-easy""]"
"[{""role"":""user"",""content"":""can you create an Trading agent""}]","The agent should transfer_to_agentconfigurationhelper","[""training""]","[""transfer_to_agentconfigurationhelper""]","[""very-easy""]"
"[{""role"":""user"",""content"":""can you update my Trading Agent Config""}]","The agent should transfer_to_agentconfigurationhelper","[""training""]","[""transfer_to_agentconfigurationhelper""]","[""easy""]"
"[{""role"":""user"",""content"":""update my agents""}]","The agent should transfer_to_agentconfigurationhelper","[""training""]","[""transfer_to_agentconfigurationhelper""]","[""easy""]"
"[{""role"":""user"",""content"":""delete agent PokemonTrainer""}]","The agent should transfer_to_agentconfigurationhelper","[""validation""]","[""transfer_to_agentconfigurationhelper""]","[""easy""]"
"[{""role"":""user"",""content"":""what are my agents""}]","The agent should transfer_to_agentconfigurationhelper","[""validation""]","[""transfer_to_agentconfigurationhelper""]","[""very-easy""]"
"[{""role"":""user"",""content"":""what are the best websearch mcps""}]","The agent should transfer_to_mcpconfigurationhelper","[""training""]","[""transfer_to_mcpconfigurationhelper""]","[""very-easy""]"
"[{""role"":""user"",""content"":""what are the best mcps""}]","The agent should transfer_to_mcpconfigurationhelper","[""training""]","[""transfer_to_mcpconfigurationhelper""]","[""very-easy""]"
"[{""role"":""user"",""content"":""can you add the exa-search mcps to my agent""}]","The agent should transfer_to_mcpconfigurationhelper","[""training""]","[""transfer_to_mcpconfigurationhelper""]","[""easy""]"
"[{""role"":""user"",""content"":""can you update my mcps config of agents PokemonTrainer""}]","The agent should transfer_to_mcpconfigurationhelper","[""training""]","[""transfer_to_mcpconfigurationhelper""]","[""medium""]"
"[{""role"":""user"",""content"":""Can you delete all the mcps exa-search of my agents""}]","The agent should transfer_to_mcpconfigurationhelper","[""validation""]","[""transfer_to_mcpconfigurationhelper""]","[""medium""]"
"[{""role"":""user"",""content"":""can you get the best car trends""}]","The agent should transfer_to_agentselectorhelper","[""training""]","[""transfer_to_agentselectorhelper""]","[""easy""]"
"[{""role"":""user"",""content"":""can you start the agent PokemonTrainer with request : What are the best teams in HearthGold-Soulsilver""}]","The agent should transfer_to_agentselectorhelper","[""training""]","[""transfer_to_agentselectorhelper""]","[""medium""]"
"[{""role"":""user"",""content"":""can you run an random agent""}]","The agent should transfer_to_agentselectorhelper","[""validation""]","[""transfer_to_agentselectorhelper""]","[""easy""]"
"[{""role"":""user"",""content"":""What is the posssibilities with SNAK""}]","The agent should transfer_to_snakragagenthelper","[""training""]","[""transfer_to_snakragagenthelper""]","[""easy""]"
"[{""role"":""user"",""content"":""What SNAK means ?""}]","The agent should transfer_to_snakragagenthelper","[""training""]","[""transfer_to_snakragagenthelper""]","[""very-easy""]"
"[{""role"":""user"",""content"":""Who created Snak ?""}]","The agent should transfer_to_snakragagenthelper","[""validation""]","[""transfer_to_snakragagenthelper""]","[""very-easy""]"
8 changes: 1 addition & 7 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,16 @@ services:
- network
ports:
- '127.0.0.1:6379:6379'
volumes:
- redis_data:/data
env_file:
- .env
command: ["redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD:?REDIS_PASSWORD is required}"]
command: ["redis-server", "--requirepass", "${REDIS_PASSWORD:?REDIS_PASSWORD is required}"]
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:?REDIS_PASSWORD is required}", "ping"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped

volumes:
redis_data:
driver: local

networks:
network:
driver: bridge
12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"node:server": "node ./mcps/snak/dist/index.js",
"start:prod": "lerna run start --scope \"@snakagent/server\"; ECODE=$? ; exit $ECODE",
"test_metrics": "jest packages/metrics/src/__tests__/metrics.test.ts",
"datasets": "tsx --tsconfig=packages/agent/tsconfig.json --env-file=.env packages/agent/src/agents/langsmith/run-datasets.ts",
"format": "prettier --write \"packages/**/*.{ts,tsx,js,jsx,json,md}\""
},
"dependencies": {
Expand All @@ -60,11 +61,10 @@
"@langchain/langgraph": "^0.4.9",
"@langchain/langgraph-checkpoint": "~0.1.1",
"@langchain/langgraph-checkpoint-postgres": "^0.1.2",
"@langchain/mcp-adapters": "^0.6.0",
"@langchain/langgraph-supervisor": "^0.0.20",
"@langchain/mcp-adapters": "^0.6.0",
"@langchain/ollama": "^0.1.6",
"@langchain/openai": "^0.3.17",
"langchain": "^0.3.34",
"@nestjs/platform-socket.io": "^11.1.1",
"@nestjs/websockets": "^11.1.1",
"add": "^2.0.6",
Expand All @@ -73,6 +73,9 @@
"dotenv": "^16.6.1",
"ethers": "^6.15.0",
"express": "^4.21.2",
"langchain": "^0.3.34",
"langsmith": "^0.3.73",
"openevals": "^0.1.1",
"pg": "^8.15.6",
"prom-client": "^15.1.3",
"socket.io": "^4.8.1",
Expand All @@ -96,6 +99,7 @@
"@types/yargs": "^17.0.33",
"@typescript-eslint/eslint-plugin": "^8.46.0",
"@typescript-eslint/parser": "^8.46.0",
"concurrently": "^9.2.1",
"eslint": "^9.37.0",
"eslint-config-prettier": "^9.1.2",
"eslint-plugin-prettier": "^5.5.4",
Expand All @@ -114,6 +118,7 @@
"turbo": "^2.5.8",
"typescript": "^5.9.3",
"typescript-eslint": "^8.46.0",
"wait-on": "^9.0.1",
"zod-to-json-schema": "^3.24.6"
},
"engines": {
Expand All @@ -125,7 +130,8 @@
"is-core-module": "2.13.1"
},
"patchedDependencies": {
"@google/[email protected]": "patches/@[email protected]"
"@google/[email protected]": "patches/@[email protected]",
"@langchain/[email protected]": "patches/@[email protected]"
}
}
}
10 changes: 6 additions & 4 deletions packages/agent/src/agents/core/snakAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
getInterruptCommand,
isInterrupt,
} from '@agents/graphs/utils/graph.utils.js';

import { v4 as uuidv4 } from 'uuid';
/**
* Main agent for interacting with the Starknet blockchain
* Supports multiple execution modes: interactive, autonomous, and hybrid
Expand Down Expand Up @@ -189,13 +189,14 @@ export class SnakAgent extends BaseAgent {
ls_model_type: chunk.metadata.ls_model_type,
ls_temperature: chunk.metadata.ls_temperature,
tokens: chunk.data.output?.usage_metadata?.total_tokens ?? null,
user_request: user_request,
content: user_request,
error: graphError,
retry: retryCount,
};

const chunkOutput: ChunkOutput = {
event: chunk.event,
agent_id: this.agentConfig.id,
run_id: chunk.run_id,
checkpoint_id: state.config.configurable?.checkpoint_id,
thread_id: state.config.configurable?.thread_id,
Expand Down Expand Up @@ -304,7 +305,7 @@ export class SnakAgent extends BaseAgent {
const initialMessages: BaseMessage[] = [
new HumanMessage(request.request),
];
const threadId = this.agentConfig.id;
const threadId = request.thread_id ? request.thread_id : uuidv4();
const configurable = {
thread_id: threadId,
user_request: {
Expand Down Expand Up @@ -392,6 +393,7 @@ export class SnakAgent extends BaseAgent {
}
yield {
event: lastChunk.event,
agent_id: this.agentConfig.id,
run_id: lastChunk.run_id,
from: GraphNode.END_GRAPH,
thread_id: threadId,
Expand All @@ -407,7 +409,7 @@ export class SnakAgent extends BaseAgent {
error: graphError,
final: true,
is_human: isInterruptHandle,
user_request: request.request,
content: request.request,
},
timestamp: new Date().toISOString(),
};
Expand Down
81 changes: 49 additions & 32 deletions packages/agent/src/agents/core/supervisorAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ import {
ChunkOutput,
ChunkOutputMetadata,
} from '../../shared/types/streaming.type.js';
import { createSupervisorGraph } from '@agents/graphs/core-graph/supervisor.graph.js';
import { CheckpointerService } from '@agents/graphs/manager/checkpointer/checkpointer.js';
import {
AIMessage,
AIMessageChunk,
HumanMessage,
} from '@langchain/core/messages';
createSupervisorGraph,
SupervisorGraph,
} from '@agents/graphs/core-graph/supervisor.graph.js';
import { CheckpointerService } from '@agents/graphs/manager/checkpointer/checkpointer.js';
import { AIMessage, HumanMessage } from '@langchain/core/messages';
import { GraphErrorType, UserRequest } from '@stypes/graph.type.js';
import { EventType } from '@enums/event.enums.js';
import { StreamEvent } from '@langchain/core/tracers/log_stream';
Expand All @@ -22,11 +21,12 @@ import {
isInterrupt,
} from '@agents/graphs/utils/graph.utils.js';
import { notify } from '@snakagent/database/queries';

import { v4 as uuidv4 } from 'uuid';
/**
* Supervisor agent for managing and coordinating multiple agents
*/
export class SupervisorAgent extends BaseAgent {
supervisorGraphInstance: SupervisorGraph | null = null;
constructor(agent_config: AgentConfig.Runtime) {
super('supervisor', AgentType.SUPERVISOR, agent_config);
}
Expand All @@ -40,23 +40,27 @@ export class SupervisorAgent extends BaseAgent {
if (!this.agentConfig) {
throw new Error('Agent configuration is required for initialization');
}

this.pgCheckpointer = await CheckpointerService.getInstance();
if (!this.pgCheckpointer) {
throw new Error('Failed to initialize Postgres checkpointer');
}
const graph = await createSupervisorGraph(this);
if (!graph) {
this.supervisorGraphInstance = await createSupervisorGraph(this);
if (!this.supervisorGraphInstance) {
throw new Error('Failed to create supervisor graph');
}
this.compiledStateGraph = graph;

this.compiledStateGraph = this.supervisorGraphInstance.getCompiledGraph();
logger.info('[SupervisorAgent] Initialized successfully');
} catch (error) {
logger.error(`[SupervisorAgent] Initialization failed: ${error}`);
throw error;
}
}

public getSupervisorGraphInstance(): SupervisorGraph | null {
return this.supervisorGraphInstance;
}

/**
* Creates a standardized chunk output
*/
Expand All @@ -78,12 +82,13 @@ export class SupervisorAgent extends BaseAgent {
ls_model_type: chunk.metadata.ls_model_type,
ls_temperature: chunk.metadata.ls_temperature,
tokens: chunk.data.output?.usage_metadata?.total_tokens ?? null,
user_request: user_request,
content: user_request,
error: graphError,
retry: retryCount,
};
const chunkOutput: ChunkOutput = {
event: chunk.event,
agent_id: this.agentConfig.id,
run_id: chunk.run_id,
checkpoint_id: state.config.configurable?.checkpoint_id,
thread_id: state.config.configurable?.thread_id,
Expand Down Expand Up @@ -154,12 +159,13 @@ export class SupervisorAgent extends BaseAgent {
* @param input - The input for execution
* @returns AsyncGenerator yielding ChunkOutput
*/
public async *execute(userRequest: UserRequest): AsyncGenerator<ChunkOutput> {
public async *execute(request: UserRequest): AsyncGenerator<ChunkOutput> {
try {
let currentCheckpointId: string | undefined = undefined;
let lastChunk: StreamEvent | undefined = undefined;
let stateSnapshot: StateSnapshot;
let isInterruptHandle = false;
let isTransferHandle = false;
if (!this.compiledStateGraph) {
throw new Error('SupervisorAgent is not initialized');
}
Expand All @@ -169,7 +175,7 @@ export class SupervisorAgent extends BaseAgent {
if (this.pgCheckpointer === null) {
throw new Error('Checkpointer is not initialized');
}
const threadId = this.agentConfig.id;
const threadId = request.thread_id ? request.thread_id : uuidv4();
const configurable = {
thread_id: threadId,
agent_config: this.agentConfig,
Expand All @@ -183,22 +189,38 @@ export class SupervisorAgent extends BaseAgent {
recursionLimit: 500,
version: 'v2' as const,
};
stateSnapshot = await this.compiledStateGraph.getState(executionConfig);
stateSnapshot = await this.compiledStateGraph.getState(executionConfig, {
subgraphs: true,
});
if (!stateSnapshot) {
throw new Error('Failed to retrieve initial graph state');
}
const executionInput = isInterrupt(stateSnapshot)
? getInterruptCommand(userRequest.request)
: { messages: [new HumanMessage(userRequest.request || '')] };
? getInterruptCommand(request.request)
: { messages: [new HumanMessage(request.request || '')] };

if (
stateSnapshot.values.transfer_to &&
stateSnapshot.values.transfer_to.length > 0
) {
await this.compiledStateGraph.updateState(executionConfig, {
transfer_to: [],
});
}
for await (const chunk of this.compiledStateGraph.streamEvents(
executionInput,
executionConfig
)) {
stateSnapshot = await this.compiledStateGraph.getState(executionConfig);
stateSnapshot = await this.compiledStateGraph.getState(
executionConfig,
{ subgraphs: true }
);
if (!stateSnapshot) {
throw new Error('Failed to retrieve graph state during execution');
}
isTransferHandle =
stateSnapshot.values.transfer_to &&
stateSnapshot.values.transfer_to.length > 0;
currentCheckpointId = stateSnapshot.config.configurable?.checkpoint_id;
lastChunk = chunk;
if (
Expand All @@ -216,30 +238,22 @@ export class SupervisorAgent extends BaseAgent {
const chunkProcessed = this.processChunkOutput(
chunk,
stateSnapshot,
userRequest.request,
request.request,
0
);
if (chunkProcessed) {
yield chunkProcessed;
}
}

if (!this.pgCheckpointer) {
throw new Error('Checkpointer is not initialized');
}

if (!isInterruptHandle) {
const startTime = Date.now();
const endTime = Date.now();
const duration = endTime - startTime;
await this.pgCheckpointer.deleteThread(threadId);
logger.info(`[SupervisorAgent] deleteThread took ${duration}ms`);
}
if (!lastChunk || !currentCheckpointId) {
throw new Error('No output from autonomous execution');
}
logger.info(
`[SupervisorAgent] Execution completed for thread ${threadId}`
);
yield {
event: lastChunk.event,
agent_id: this.agentConfig.id,
run_id: lastChunk.run_id,
from: SupervisorNode.END_GRAPH,
thread_id: threadId,
Expand All @@ -251,7 +265,10 @@ export class SupervisorAgent extends BaseAgent {
error: undefined,
final: true,
is_human: isInterruptHandle,
user_request: userRequest.request,
content: request.request,
transfer_to: isTransferHandle
? stateSnapshot.values.transfer_to
: null,
},
timestamp: new Date().toISOString(),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,5 @@ export const STRING_LIMITS = {
'execution.max_description_length'
),
} as const;

export const MAX_SUPERVISOR_MESSAGE = 30;
1 change: 0 additions & 1 deletion packages/agent/src/agents/graphs/core-graph/agent.graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import {
Memories,
skipValidationType,
TaskType,
UserRequest,
userRequestWithHITL,
} from '../../../shared/types/index.js';
import { MemoryStateManager } from '../manager/memory/memory-utils.js';
Expand Down
Loading