feat: add run mode: step#343
Merged
Merged
Conversation
Contributor
|
This PR is likely to resolve #293 also. |
Owner
|
This may also be a way to resolve #345. |
brainlid
approved these changes
Jul 28, 2025
Owner
|
I'm considering adding an option to with something like: LLMChain.run(chain, mode: :step, should_continue?: &check_some_condition/1)It would basically be like the Would that be helpful in your situation as well? |
Contributor
Author
|
Thank you @brainlid 😄 It does! And looks super clean. 💪 |
CaiqueMitsuoka
added a commit
to CaiqueMitsuoka/langchain
that referenced
this pull request
Aug 18, 2025
…cally As suggested by @Branlid at brainlid#343. This adds a new option for `mode: :step` to use a `should_continue?` function. This allows fine grained control of the `run/2` loop when no change to the chain is required.
CaiqueMitsuoka
added a commit
to CaiqueMitsuoka/langchain
that referenced
this pull request
Aug 18, 2025
…cally As suggested by @Branlid at brainlid#343. This adds a new option for `mode: :step` to use a `should_continue?` function. This allows fine grained control of the `run/2` loop when no change to the chain is required.
CaiqueMitsuoka
added a commit
to CaiqueMitsuoka/langchain
that referenced
this pull request
Aug 18, 2025
…cally As suggested by @Branlid at brainlid#343. This adds a new option for `mode: :step` to use a `should_continue?` function. This allows fine grained control of the `run/2` loop when no change to the chain is required.
CaiqueMitsuoka
added a commit
to CaiqueMitsuoka/langchain
that referenced
this pull request
Aug 21, 2025
…cally As suggested by @Branlid at brainlid#343. This adds a new option for `mode: :step` to use a `should_continue?` function. This allows fine grained control of the `run/2` loop when no change to the chain is required.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hey 👋
This PR introduces a new mode called
stepforLangChain.Chains.LLMChain.run/2.Context
At Cloudwalk, we are using Langchain to serve 4M users, all with an active assistant.
With that, we have been hitting a few use cases that are not supported by langchain which has made us use a fork with an option to raise an error from tool calls.
This has been hard to keep up with new releases and also contribute back to the project.
The problem
The existing chain execution modes (
:until_success,:while_needs_response, and the default mode) don't provide the granular control we need for deterministic workflows in regulated environments.Our core challenge: We need to conditionally stop execution based on which tools are called, but the current modes force us to decide the execution strategy upfront, before we know what tools the LLM will choose.
Consider this hipothetical scenario: We have a chain with two tools:
wire_transfer(amount, account)- Executes a money transfer. Must stop for user confirmation.user_debts()- Returns outstanding debts. Should continue to let LLM explain the results.The problem becomes apparent when a user says "Pay my debts":
Why existing modes fail:
:until_success- Stops after the first successful tool call. Works forwire_transferbut fails foruser_debts(No explanation of the result).:while_needs_response- Continues until LLM provides a final response. Works foruser_debtsbut fails forwire_transfer(Will explain the tool result, it shouldn't).Default mode - Behaves like
:until_success, same limitations.:until_success:while_needs_responseThe fundamental issue: We can't know which execution mode we need until we see which tools the LLM decides to call. By then, we're already committed to a mode that might be wrong for the scenario.
What we need is the ability to inspect the chain state after each step and decide whether to continue - giving us the control to implement the deterministic behavior our regulated environment requires.
The solution
Optionally giving control of the loop. While the loop has served and still is serving us well for some use cases it imposes the aforementioned limitations.
A stepped execution will give clients control over execution to implement their own loops. While still being able to call other modes in the middle of the execution.
With this mode we are able to stop on the major chain events: assistant response, tool calls and tool responses.
While still leveraging fallback models and all the data modeling from Langchain.
This allows clients to inspect the entire chain state and even alter chain state between executions.
For our use case, this will allow us to achieve the UX we need, and will allow new use cases like extending the chain with dynamic few-shot examples/tools in mid execution for example.