Skip to content

feat: add stop_run State key and TokenBudgetHook - #12411

Merged
anakin87 merged 8 commits into
mainfrom
agent-stop-run
Aug 21, 2026
Merged

feat: add stop_run State key and TokenBudgetHook#12411
anakin87 merged 8 commits into
mainfrom
agent-stop-run

Conversation

@anakin87

@anakin87 anakin87 commented Aug 19, 2026

Copy link
Copy Markdown
Member

Related Issues

Proposed Changes:

  • add stop_run State key
    • minimal implementation: the key is read in Agent._run_step before the LLM call
    • the key carries the exit_reason
    • if the run was already about to end, the exit_reason is the original one
  • add TokenBudgetHook to test the abstraction above

How did you test it?

CI, new tests

Checklist

  • I have read the contributors guidelines and the code of conduct.
  • I have updated the related issue with new insights and changes.
  • I have added unit tests and updated the docstrings.
  • I've used one of the conventional commit types for my PR title: fix:, feat:, build:, chore:, ci:, docs:, style:, refactor:, perf:, test: and added ! in case the PR includes breaking changes.
  • I have documented my code.
  • I have added a release note file, following the contributors guidelines.
  • I have run pre-commit hooks and fixed any issue.

@vercel

vercel Bot commented Aug 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
haystack-docs Ignored Ignored Preview Aug 21, 2026 8:51am

Request Review

@github-actions github-actions Bot added topic:tests type:documentation Improvements on the docs labels Aug 19, 2026
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  haystack/components/agents
  agent.py
  haystack/core/pipeline
  pipeline.py
  haystack/hooks/budget
  __init__.py
  hooks.py
Project Total  

This report was generated by python-coverage-comment-action

@anakin87 anakin87 changed the title feat: stop_run state key + TokenBudgetHook feat: add stop_run State key and TokenBudgetHook Aug 20, 2026
assert agent.chat_generator.run.call_count == 1


class TestStopRun:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to exactly understand how the Agent behaves with this key (in relation to hooks and exit reasons), I recommend taking a quick look at the following tests

@anakin87
anakin87 marked this pull request as ready for review August 20, 2026 14:16
@anakin87
anakin87 requested a review from a team as a code owner August 20, 2026 14:16
@anakin87
anakin87 requested review from sjrl and removed request for a team August 20, 2026 14:16
Comment thread haystack/components/agents/agent.py
Comment on lines +65 to +66
if total_tokens >= self.max_total_tokens:
state.set("stop_run", "token_budget_exceeded")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also wonder if optionally setting a final message in state.data["messages"] would be useful. E.g. the final message could be "Agent stopped because token budget was exceeded".

This could be an optional init param of this hook. WDYT?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have strong opinions about this point.
Do you think that this would be helpful? Who would be the final user of this?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm imagining the case if someone is hosting an Agent in Hayhooks and that whatever the last message is in State is what the end user will see. Right now it would be a tool call result which could be confusing.

I think it can be solved here in the Hook or we would need to add a check for that in the Hayhooks app to provide an actionable message to the user

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I see. What about a final_message: ChatMessage | bool = False

  • False: do nothing
  • True: default final message
  • ChatMessage: provided message

Just an idea, I can improve the design (if you agree on the direction).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I like the direction!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in a simplified way in 774e784

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! And I agree with the off by default. I also realized that users anyways may prefer to create an after_run hook that manages what the final message should be based on reading the exit reason

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, agree on after_run hook.

total_tokens = _first_numeric(usage, ("total_tokens",))
if not total_tokens:
total_tokens = _first_numeric(usage, _INPUT_TOKEN_KEYS) + _first_numeric(usage, _OUTPUT_TOKEN_KEYS)
if total_tokens >= self.max_total_tokens:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think adding a logger warning message here could be helpful so it appears in logs if the Agent is running over the token budget.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in af83ca3

@sjrl sjrl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@anakin87
anakin87 enabled auto-merge (squash) August 21, 2026 08:59
@anakin87
anakin87 merged commit 53901d9 into main Aug 21, 2026
25 checks passed
@anakin87
anakin87 deleted the agent-stop-run branch August 21, 2026 09:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:tests type:documentation Improvements on the docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants