“Why, when I perform an update inside a command or tool, the updated values are not reflected in the next step — it’s as if the update didn’t happen at all and the original values are still being used?”
my tool->
@tool(return_direct=True)
async def check_updated_fields_tool(
tool_call_id: Annotated[str, InjectedToolCallId],
populated_form_fields: Annotated[
list[dict] | dict, InjectedState("populated_form_fields")
],
field: str,
label: str,
value: str,
type: str,
):
"""
Update a specific field in the PDF form with the provided value.
This tool updates a single field in the PDF form using the original field name,
user-provided value, and the field type. This is the main mechanism for writing
values into the PDF.
Only invoke this tool for one field at the time.
Args:
field (str): Internal field name from the PDF (`original_field_name`).
label (str):Field name which is showed to the users on the surface(labeled_name)
value (str): Value to write (e.g., "true" / "false" for checkboxes).
type (str): Field type ("text", "checkbox", "date", "number", or "dropdown").
Returns:
Command: Updates LangGraph state with the submitted field and confirmation message.
"""
submited_field_data = {
"field": field,
"label": label,
"value": value,
"type": type,
}
populated_form_fields.append(submited_field_data)
log.info(f"New submission: {submited_field_data}")
return Command(
update={
"populated_form_fields": populated_form_fields,
"updated_form_field": {},
"messages": [
ToolMessage(
(
f"Field manually filled by user: '{label}' (type: {type}, value: '{value}').\n"
f"Make sure to skip this field in the next questions, as the user has already provided the value manually.\n\n"
f"The following fields have been populated so far:\n"
f"{populated_form_fields}"
),
tool_call_id=tool_call_id,
)
],
},
goto="__end__",
)
My agent->
def build_pdf_field_mapper_agent(
llm_model: str = "gpt-4.1",
tools: List[Callable[..., Any]] = None,
system_prompt: Union[str, SystemMessage] = FIELD_MAPPING_AGENT_PROMPT,
):
llm = ChatOpenAI(model=llm_model, temperature=0)
model = llm.bind_tools(tools, tool_choice="required")
def generate_prompt_from_state(state: Dict[str, Any]) -> List[Any]:
messages = state.get("messages", [])
updated_form_field = state.get("updated_form_field", {})
system_msg = (
system_prompt
if isinstance(system_prompt, SystemMessage)
else SystemMessage(content=system_prompt)
)
prompt_messages = [system_msg]
prompt_messages.extend(messages)
if updated_form_field:
field_json = json.dumps(updated_form_field, ensure_ascii=False)
prompt_messages.append(
HumanMessage(
content=(
f"The following field has been filled manually: {field_json}. "
"Please determine the corresponding field and update it using check_updated_fields_tool."
)
)
)
return prompt_messages
# Create the agent using LangGraph's create_react_agent with the prompt function
agent = create_react_agent(
model=model, tools=tools, prompt=generate_prompt_from_state, state_schema=State
)
return agent
agent = build_pdf_field_mapper_agent(tools=[check_updated_fields_tool])
async def process_user_updated_field(state: State) -> Command[Literal["__end__"]]:
try:
# Postavi recursion_limit na npr. 25 (možeš prilagoditi)
result = await agent.ainvoke(state, {"recursion_limit": 25})
except GraphRecursionError:
# Ako je recursion limit dostignut, zaustavi agent i vrati poruku
return Command(
update={
"messages": [
SystemMessage(
content="Agent je zaustavljen zbog dostignutog limita iteracija."
)
],
"updated_form_field": {}, # očisti da ne bi ponovo pokrenuo
},
goto="__end__",
)
# Ako nema rezultata ili nema više polja za ažuriranje, zaustavi graf
if not result or not result.get("updated_form_field"):
return Command(goto="__end__")
# Inače nastavi sa ažuriranim stanjem
return Command(update=result)
Here is trace:
Second one where updated doesnt occur:
In the below image it is update correctly inside Command but in the START node when next step is invoked by user input state variables are the same doesnt changed as in image