🛠️ DevOps Support Agent with Human in the Loop
Notebook by Amna Mubashar
This notebook demonstrates how a Haystack Agent can interactively ask for user input when it's uncertain about the next step. We'll build a Human-in-the-Loop tool that the Agent can call dynamically. When the Agent encounters ambiguity or incomplete information, it will ask for more input from the human to continue solving the task.
For this purpose, we will create a DevOps Support Agent.
CI/CD pipelines occasionally fail for reasons that can be hard to diagnose including manually—broken tests, mis-configured environment variables, flaky integrations, etc.
The support Agent is created using Haystack Tools and Agent and will perform the following tasks:
- Check for any failed CI workflows
- Fetch build logs and status
- Lookup and analyze git commits
- Suggest next troubleshooting steps
- Escalate to humans via Human-in-Loop tool
Install the required dependencies
Next, we configure our variables. We need to set the OPENAI_API_KEY for OpenAIChatGenerator and
a GITHUB_TOKEN with appropriate permissions to access repository information, CI logs, and commit history. Make sure your GitHub token has sufficient access rights to the repository you want to analyze.
Define Tools
We start by defining the tools which will be used by our Agent.
git_list_commits_tool: Fetches and formats the most recent commits on a given GitHub repository and branch.
Useful for quickly surfacing the latest changes when diagnosing CI failures or code regressions.
git_diff_tool: Retrieves the patch (diff) between two commits or branches in a GitHub repository.
Enables side-by-side inspection of code changes that may have triggered test failures.
ci_status_tool: Checks the most recent GitHub Actions workflow runs for failures, downloads their logs, and extracts the first failed test name and error message. Automates root-cause identification by surfacing the exact test and error that caused a pipeline to fail.
shell_tool: Executes a local shell command with a configurable timeout, capturing stdout or returning detailed error output. Great for grepping, filtering, or tailing CI log files before passing only the relevant snippets to the LLM.
human_in_loop_tool: Prompts the user with a clarifying question via input() when the Agent encounters ambiguity or needs additional information. Ensures the Agent only interrupts for human feedback when strictly necessary.
Create and Configure the Agent
Create a Haystack Agent instance and configure its behavior with a system prompt and tools.
Agent Introspection with Streaming
Haystack supports streaming of ToolCalls and ToolResults during Agent execution. By passing a streaming_callback to the Agent, you can observe the internal reasoning process in real time.
This allows you to:
- See which tools the Agent decides to use.
- Inspect the arguments passed to each tool.
- View the results returned from each tool before the final answer is generated.
This is especially useful for debugging and transparency in complex multi-step reasoning workflows of Agent.
Note: You can pass any streaming_callback function. The print_streaming_chunk utility function in Haystack is configured to stream tool calls and results by default.
[TOOL CALL]
Tool: human_in_loop_tool
Arguments: {"question":"Please provide the GitHub repository in 'owner/name' format for which you want to check CI failures."}
[TOOL RESULT]
deepset-ai/haystack
[TOOL CALL]
Tool: ci_status_tool
Arguments: {"repo":"deepset-ai/haystack","per_page":50}
[TOOL RESULT]
Found 2 failed run(s):
- **Run ID**: 14994639315
**Branch**: update-tools-strict-openai
**Event**: pull_request
**Created At**: 2025-05-13T10:45:32Z
**Failures by Suite**:
â–¶ **Suite**: `Unit ubuntu-latest`
- **2025-05-13T10:47:25.4802006Z**: 2025-05-13T10:47:25.4802006Z ERROR haystack.core.serialization:serialization.py:263 Failed to import class 'Nonexisting.DocumentStore'
- **2025-05-13T10:47:26.4669164Z**: 2025-05-13T10:47:26.4669164Z test/components/converters/test_csv_to_document.py::TestCSVToDocument::test_run_error_handling
- **2025-05-13T10:47:26.6024332Z**: 2025-05-13T10:47:26.6024332Z test/components/converters/test_docx_file_to_document.py::TestDOCXToDocument::test_run_error_wrong_file_type
[... additional test failure details omitted for brevity ...]
[... agent analysis and recommendations continue below ...]
Here’s what I found for the most recent failing run:
**Run ID**: 14994639315
**Branch**: update-tools-strict-openai
| Test Suite | Test / Step | Error |
|-------------------------------|-----------------------------------------------------------|-----------------------------------------------------------------------------|
| 0_lint.txt (→ `lint`) | `Process completed with exit code 4` | Linter returned code 4 (no details in output) |
| Integration · ubuntu-latest | TestMarkdownToDocument::test_run_error_handling | “Task exception was never retrieved” / `RuntimeError('Event loop is closed')` |
| Integration · windows-latest | TestMarkdownToDocument::test_run_error_handling | `RuntimeError('Event loop is closed')` (unraisableexception warnings) |
| Integration · macos-latest | TestMarkdownToDocument::test_run_error_handling | `RuntimeError('Event loop is closed')` |
Next Steps:
1. **Fix Lint Exit Code 4**
- Run the lint job locally (`flake8` or `hatch run lint`) to reproduce the exit-code and capture missing details.
- Adjust `.flake8`/`pre-commit` config or fix any new style violations so that the lint step exits zero.
2. **Resolve “Event loop is closed” in Markdown converter tests**
- In `haystack/components/converters/markdown.py` (or its test), ensure any `asyncio` event loop is properly created/closed.
- Switch to `pytest-asyncio` fixtures (e.g. use `@pytest.mark.asyncio` and the provided `event_loop` fixture) so that the loop remains open for the duration of `test_run_error_handling`.
3. Rerun CI to confirm both the lint and integration failures are resolved.