langgraph conditionalEdge not seem to be working for new Graph() only workes for stategraph and messageGraph #45

Closed
opened 2026-02-15 17:14:56 -05:00 by yindo · 7 comments
Owner

Originally created by @jithinagiboson on GitHub (Jul 8, 2024).

langraph version 0.0.26

I have langgraph which is a replica of langchain sql agent
but when i run the nodes with individual edges it worked
but when i added conditionalEdge its not taken as a edge
it says the first node is a dead end
this below is the diagram of my a idea
its actualy a by directional edge

image
// ROUTER function
const router=async (state)=>{
log("-------ROUTER---------")
let {result}=state
let action=result["Action"]
log(action)
// return action//next action
// return "list-tables-sql"
return "list-tables-sql"
}
// query-sql,info-sql,list-tables-sql,query-checker
// GRAPH

graph.addEdge("list-tables-sql", "info-sql");
graph.addEdge("info-sql", "query-checker");
graph.addEdge("query-checker", END);

graph.addEdge(START, "query");
graph.addEdge("query", "list-tables-sql"); // this line only work if i coment this it says query is a dead end
// graph.addEdge("query", "info-sql");
// graph.addEdge(START,"list-tables-sql");
graph.addConditionalEdges(
'query',
// Assess agent decision
router,
{
"list-tables-sql":"list-tables-sql"
}
);
const runnable = graph.compile();

Originally created by @jithinagiboson on GitHub (Jul 8, 2024). langraph version 0.0.26 I have langgraph which is a replica of langchain sql agent but when i run the nodes with individual edges it worked but when i added conditionalEdge its not taken as a edge it says the first node is a dead end this below is the diagram of my a idea its actualy a by directional edge ![image](https://github.com/langchain-ai/langgraphjs/assets/53430451/d86e8835-3e2c-416f-ae28-26182d248fa7) // ROUTER function const router=async (state)=>{ log("-------ROUTER---------") let {result}=state let action=result["Action"] log(action) // return action//next action // return "list-tables-sql" return "list-tables-sql" } // query-sql,info-sql,list-tables-sql,query-checker // GRAPH graph.addEdge("list-tables-sql", "info-sql"); graph.addEdge("info-sql", "query-checker"); graph.addEdge("query-checker", END); graph.addEdge(START, "query"); graph.addEdge("query", "list-tables-sql"); // this line only work if i coment this it says query is a dead end // graph.addEdge("query", "info-sql"); // graph.addEdge(START,"list-tables-sql"); graph.addConditionalEdges( 'query', // Assess agent decision router, { "list-tables-sql":"list-tables-sql" } ); const runnable = graph.compile();
yindo closed this issue 2026-02-15 17:14:56 -05:00
Author
Owner

@jithinagiboson commented on GitHub (Jul 8, 2024):

my package.json
{
"name": "ai-chart-generator",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"start": "nodemon index.js",
"agent": "nodemon ./modules/database-ai/agent.js",
"test": "nodemon ./modules/database-ai/test.js",
"graph": "nodemon ./modules/lang-graph/index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"@langchain/community": "^0.2.17",
"@langchain/core": "^0.2.12",
"@langchain/langgraph": "^0.0.26",
"@langchain/openai": "^0.2.0",
"dotenv": "^16.4.5",
"langchain": "^0.2.8",
"langsmith": "^0.1.34",
"mysql": "^2.18.1",
"node-querybuilder": "^2.1.1",
"typeorm": "^0.3.20",
"xss": "^1.0.15"
}
}

@jithinagiboson commented on GitHub (Jul 8, 2024): my package.json { "name": "ai-chart-generator", "version": "1.0.0", "description": "", "main": "index.js", "type": "module", "scripts": { "start": "nodemon index.js", "agent": "nodemon ./modules/database-ai/agent.js", "test": "nodemon ./modules/database-ai/test.js", "graph": "nodemon ./modules/lang-graph/index.js" }, "author": "", "license": "ISC", "dependencies": { "@langchain/community": "^0.2.17", "@langchain/core": "^0.2.12", "@langchain/langgraph": "^0.0.26", "@langchain/openai": "^0.2.0", "dotenv": "^16.4.5", "langchain": "^0.2.8", "langsmith": "^0.1.34", "mysql": "^2.18.1", "node-querybuilder": "^2.1.1", "typeorm": "^0.3.20", "xss": "^1.0.15" } }
Author
Owner

@jithinagiboson commented on GitHub (Jul 8, 2024):

const graph = new Graph();

...
....
...
const runnable = graph.compile();

// new HumanMessage("elephents")
// For Message graph, input should always be a message or list of messages.
let state = { input: "list 1st 20 customers and genres " };
log(state);
const res = await runnable.invoke(state);

i use a custom js object as state

@jithinagiboson commented on GitHub (Jul 8, 2024): const graph = new Graph(); ... .... ... const runnable = graph.compile(); // new HumanMessage("elephents") // For Message graph, input should always be a message or list of messages. let state = { input: "list 1st 20 customers and genres " }; log(state); const res = await runnable.invoke(state); i use a custom js object as state
Author
Owner

@vbarda commented on GitHub (Jul 8, 2024):

@jithinagiboson could you please explain the step-by-step flow that you're trying to implement? it would also be helpful to see the full graph implementation in one code snippet that has graph state, nodes, edges and the compiled graph.

also, I believe you can just use a prebuilt ReAct agent to achieve the same behavior as langchain's SQL agent:

import { createReactAgent } from "@langchain/langgraph/prebuilt"
import { ChatAnthropic } from "@langchain/anthropic"

const tools = []  // your SQL tools defined here
const llm = new ChatAnthropic({ model: "claude-3-haiku-20240307" })  // or whichever model you're using
const agent = createReactAgent({ llm, tools })
const res = await agent.invoke(
  { messages: [["user", "list 1st 20 customers and genres"]] }
)
@vbarda commented on GitHub (Jul 8, 2024): @jithinagiboson could you please explain the step-by-step flow that you're trying to implement? it would also be helpful to see the full graph implementation in one code snippet that has graph state, nodes, edges and the compiled graph. also, I believe you can just use a prebuilt ReAct agent to achieve the same behavior as langchain's SQL agent: ```js import { createReactAgent } from "@langchain/langgraph/prebuilt" import { ChatAnthropic } from "@langchain/anthropic" const tools = [] // your SQL tools defined here const llm = new ChatAnthropic({ model: "claude-3-haiku-20240307" }) // or whichever model you're using const agent = createReactAgent({ llm, tools }) const res = await agent.invoke( { messages: [["user", "list 1st 20 customers and genres"]] } ) ```
Author
Owner

@jithinagiboson commented on GitHub (Jul 9, 2024):

my requirements
-use an opensource ai model for text to sql query
current issues faced

using an sql agent doesnt give me much control over the outcome.And sql agent in js already have bug its only prompt is default to sqlite so i had to hard code it to mysql.
what i did was using the same prompt used by sql agent inside langraph
i used the llm responce to identify the too name to use and tried to route to that node

the below


graph.addNode("query",` async (state) => {
  log("------------NODE QUERY------------");
  log("state", state);
 
  const parser = new JsonOutputParser();
  
  const chain = prompt.pipe(modelJSON).pipe(parser);

  let agentSteps = [];
  let result = await chain.invoke({
    dialect: DIALECT,
    input: state.input,
    agentSteps: agentSteps,
    agent_scratchpad: "",
  });
  agentSteps = [{ Thought: result["Thought"] }];

  return { input: state.input, result: result, intermediateSteps: agentSteps };
});

graph.addNode("list-tables-sql", async (state) => {
  log("------------NODE list-tables-sql------------");
  log("state", state);


 
  const prompt = ChatPromptTemplate.fromTemplate(lama3_70b_prompt);

  const parser = new JsonOutputParser();

  const chain = prompt.pipe(modelJSON).pipe(parser);

  //CALL TOOLS
  let tableNameArray = db.allTables.map((a) => a.tableName); //get all table names

//   log("tableNameArray",tableNameArray)
//   process.exit()
  // let default_result={result:{
  //     Question: state.input,
  //     Thought: 'I should look at the tables in the database to see what I can query.',
  //     Action: 'list-tables-sql',
  //     'Action Input': '',
  //     Observation: getArray2Text(textArray) //'Album,Artist,Customer,Employee,Genre,Invoice,InvoiceLine,MediaType,Playlist,PlaylistTrack,Track'
  //   }}


  let agentSteps = {
    Action: state.result["Action"],
    "Action Input": state.result["Action Input"],
    Observation: getArray2Text(tableNameArray),
    Thought: "",
  };

  state.intermediateSteps.push(agentSteps);

  let concatAgentSteps =arrayJSON2Text(state.intermediateSteps);


  let result = await chain.invoke({
    dialect: DIALECT,
    input: state.input,
    agent_scratchpad: concatAgentSteps,
  }); //llm call

  state.intermediateSteps[state.intermediateSteps.length - 1].Thought =
    result["Thought"]; //thought from llm
dialect:DIALECT,input:state.input,agent_steps:state.agent_steps&&state.agent_steps+'\n'+JSON2Text(agent_steps),agent_scratchpad:JSON2Text(agent_steps) }))

  log("list-tables-sql RESULT", result);

  return {
    input: state.input,
    result: result,
    intermediateSteps: state.intermediateSteps,
  };
});

graph.addEdge(START, "query");
graph.addEdge("query", "list-tables-sql"); // this line only work if i coment this it says query is a dead end
// graph.addEdge("query", "info-sql");
// graph.addEdge(START,"list-tables-sql");
graph.addConditionalEdges(
'query',
// Assess agent decision
router,
{
"list-tables-sql":"list-tables-sql"
}
);


// ROUTER function
const router=async (state)=>{
log("-------ROUTER---------")
let {result}=state
let action=result["Action"]
log(action)
// return action//next action
// return "list-tables-sql"
return "list-tables-sql"// just hard coded to test query to list table flow
}

this is the basic flow one node result has and action input which shloud be used for conditional routing to the next node
but unfortunatly its not taken as an edge at all

@jithinagiboson commented on GitHub (Jul 9, 2024): my requirements -use an opensource ai model for text to sql query current issues faced - i have used open sorce model using langchain ollama so tool calling agent was not working properly -i was trying to implement langchain sql-agent work flow using langraph https://smith.langchain.com/public/da3bb6ee-6e51-45be-a2de-4703711a6886/r using an sql agent doesnt give me much control over the outcome.And sql agent in js already have bug its only prompt is default to sqlite so i had to hard code it to mysql. what i did was using the same prompt used by sql agent inside langraph i used the llm responce to identify the too name to use and tried to route to that node the below ``` graph.addNode("query",` async (state) => { log("------------NODE QUERY------------"); log("state", state); const parser = new JsonOutputParser(); const chain = prompt.pipe(modelJSON).pipe(parser); let agentSteps = []; let result = await chain.invoke({ dialect: DIALECT, input: state.input, agentSteps: agentSteps, agent_scratchpad: "", }); agentSteps = [{ Thought: result["Thought"] }]; return { input: state.input, result: result, intermediateSteps: agentSteps }; }); graph.addNode("list-tables-sql", async (state) => { log("------------NODE list-tables-sql------------"); log("state", state); const prompt = ChatPromptTemplate.fromTemplate(lama3_70b_prompt); const parser = new JsonOutputParser(); const chain = prompt.pipe(modelJSON).pipe(parser); //CALL TOOLS let tableNameArray = db.allTables.map((a) => a.tableName); //get all table names // log("tableNameArray",tableNameArray) // process.exit() // let default_result={result:{ // Question: state.input, // Thought: 'I should look at the tables in the database to see what I can query.', // Action: 'list-tables-sql', // 'Action Input': '', // Observation: getArray2Text(textArray) //'Album,Artist,Customer,Employee,Genre,Invoice,InvoiceLine,MediaType,Playlist,PlaylistTrack,Track' // }} let agentSteps = { Action: state.result["Action"], "Action Input": state.result["Action Input"], Observation: getArray2Text(tableNameArray), Thought: "", }; state.intermediateSteps.push(agentSteps); let concatAgentSteps =arrayJSON2Text(state.intermediateSteps); let result = await chain.invoke({ dialect: DIALECT, input: state.input, agent_scratchpad: concatAgentSteps, }); //llm call state.intermediateSteps[state.intermediateSteps.length - 1].Thought = result["Thought"]; //thought from llm dialect:DIALECT,input:state.input,agent_steps:state.agent_steps&&state.agent_steps+'\n'+JSON2Text(agent_steps),agent_scratchpad:JSON2Text(agent_steps) })) log("list-tables-sql RESULT", result); return { input: state.input, result: result, intermediateSteps: state.intermediateSteps, }; }); ``` ``` graph.addEdge(START, "query"); graph.addEdge("query", "list-tables-sql"); // this line only work if i coment this it says query is a dead end // graph.addEdge("query", "info-sql"); // graph.addEdge(START,"list-tables-sql"); graph.addConditionalEdges( 'query', // Assess agent decision router, { "list-tables-sql":"list-tables-sql" } ); // ROUTER function const router=async (state)=>{ log("-------ROUTER---------") let {result}=state let action=result["Action"] log(action) // return action//next action // return "list-tables-sql" return "list-tables-sql"// just hard coded to test query to list table flow } ``` this is the basic flow one node result has and action input which shloud be used for conditional routing to the next node but unfortunatly its not taken as an edge at all
Author
Owner

@jithinagiboson commented on GitHub (Jul 9, 2024):

i think the issue may be with
import { Graph} from "@langchain/langgraph";
Graph doesnt seem to work with conditional edge
the below code work with MessageGraph

import { START, END, MessageGraph, Graph,StateGraph, } from "@langchain/langgraph";
import { log } from "../helper/util.js";
import { HumanMessage } from "@langchain/core/messages";


const model=(state)=>{
log('--- AGENT-----')
return state
}


const action=(state)=>{
    log('--- ACTION-----')
    return state
    }
const graph = new MessageGraph();

const workflow = new MessageGraph() //new Graph()

  .addNode("agent", model)
  .addNode("action",action);


  const shouldContinue=(state)=>{
    log("shouldContinue")
    return "action"
  }
  workflow.addConditionalEdges("agent", shouldContinue);
  workflow.addEdge(START, "agent");
  workflow.addEdge("action", END);


  let app=workflow.compile()
 app.invoke({messages:[new HumanMessage("what about ny")]})

OUTPUT
[nodemon] starting node modules/lang-graph/route-test.js
--- AGENT-----
shouldContinue
--- ACTION-----
[nodemon]

@jithinagiboson commented on GitHub (Jul 9, 2024): i think the issue may be with import { Graph} from "@langchain/langgraph"; Graph doesnt seem to work with conditional edge the below code work with MessageGraph ``` import { START, END, MessageGraph, Graph,StateGraph, } from "@langchain/langgraph"; import { log } from "../helper/util.js"; import { HumanMessage } from "@langchain/core/messages"; const model=(state)=>{ log('--- AGENT-----') return state } const action=(state)=>{ log('--- ACTION-----') return state } const graph = new MessageGraph(); const workflow = new MessageGraph() //new Graph() .addNode("agent", model) .addNode("action",action); const shouldContinue=(state)=>{ log("shouldContinue") return "action" } workflow.addConditionalEdges("agent", shouldContinue); workflow.addEdge(START, "agent"); workflow.addEdge("action", END); let app=workflow.compile() app.invoke({messages:[new HumanMessage("what about ny")]}) ``` OUTPUT [nodemon] starting `node modules/lang-graph/route-test.js` --- AGENT----- shouldContinue --- ACTION----- [nodemon]
Author
Owner

@jithinagiboson commented on GitHub (Jul 9, 2024):

i have solved my issue by using StateGrpah() instead of Graph()

@jithinagiboson commented on GitHub (Jul 9, 2024): i have solved my issue by using StateGrpah() instead of Graph()
Author
Owner

@vbarda commented on GitHub (Jul 9, 2024):

ah, yes, it should be a StateGraph, that's correct! glad it worked

@vbarda commented on GitHub (Jul 9, 2024): ah, yes, it should be a `StateGraph`, that's correct! glad it worked
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraphjs#45