HumanInputTool Inside a Skill — Meeting Notes Summarizer¶
This notebook shows that HITL is not only an agent-level concern — it can be embedded directly inside a reusable skill.
The meeting-notes-summarizer skill uses HumanInputTool with constrained
choices to ask the operator two questions before producing output:
- Format —
bullet-pointsorprose - Level of detail —
briefordetailed
Any agent that loads this skill gets the human-input behaviour automatically, without the caller knowing or configuring it.
# Uncomment the line below to install `llm-agents-from-scratch` from PyPI
# !pip install llm-agents-from-scratch
Running an Ollama service¶
To execute the code provided in this notebook, you'll need to have Ollama
installed on your local machine and have its LLM hosting service running.
To download Ollama, follow the instructions found on this page:
https://ollama.com/download. After downloading and installing Ollama, you
can start a service by opening a terminal and running ollama serve.
import os
import shutil
import subprocess
import time
import urllib.error
import urllib.request
def ensure_ollama(host="http://localhost:11434", timeout=15):
"""Start Ollama if not already running and wait until responsive."""
def _up():
try:
urllib.request.urlopen(f"{host}/api/tags", timeout=1)
return True
except (urllib.error.URLError, ConnectionError, TimeoutError):
return False
if _up():
return print(f"\u2713 Ollama already running at {host}")
ollama_path = shutil.which("ollama")
if ollama_path is None:
for candidate in [
"/teamspace/studios/this_studio/.local/bin/ollama",
"/usr/local/bin/ollama",
"/usr/bin/ollama",
]:
if os.path.exists(candidate):
ollama_path = candidate
break
if ollama_path is None:
raise RuntimeError(
"Could not find the ollama binary. Install with: "
"curl -fsSL https://ollama.com/install.sh | sh",
)
print(f"Starting Ollama server ({ollama_path})...")
subprocess.Popen(
[ollama_path, "serve"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
deadline = time.time() + timeout
while time.time() < deadline:
if _up():
return print(f"\u2713 Ollama up and running at {host}")
time.sleep(0.5)
raise RuntimeError(f"Ollama did not start within {timeout}s")
use_cloud = "OLLAMA_API_KEY" in os.environ
ensure_ollama() if not use_cloud else print("\u2713 Using Ollama Cloud")
✓ Using Ollama Cloud
model = "qwen3.5:397b-cloud" if use_cloud else "qwen3:14b"
host = "https://ollama.com" if use_cloud else None
import logging
from llm_agents_from_scratch import LLMAgent
from llm_agents_from_scratch.llms import OllamaLLM
from llm_agents_from_scratch.logger import enable_console_logging
from llm_agents_from_scratch.tools.default import HumanInputTool
enable_console_logging(logging.INFO)
human_input_tool = HumanInputTool()
llm = OllamaLLM(host=host, model=model, think=False, json_prompt_mode=use_cloud)
agent = LLMAgent(llm=llm, tools=[human_input_tool])
TRANSCRIPT = """\
Sprint 14 Planning — 2026-06-27
Attendees: Priya (PM), Marcus (Lead Eng), Leila (Backend),
Tom (Frontend), Ana (QA)
Priya opened by reviewing Sprint 13 velocity: 42 points delivered against a
target of 45. Two stories were rolled over — the pagination refactor (8 pts)
and the email digest feature (5 pts). Both are high priority for Sprint 14.
Marcus flagged a dependency risk: the pagination refactor depends on a database
migration scheduled for next Tuesday. If the migration slips, the refactor
cannot be merged. The team agreed to move the migration to Monday to de-risk.
Leila volunteered to pick up the email digest feature and estimated three days
of backend work. Tom said he'd need one day of frontend work once Leila's API
is ready. Ana will write the test plan today so it's ready for review by
Wednesday.
Sprint 14 commitments (44 points total):
- Pagination refactor: 8 pts — Marcus, Leila
- Email digest: 5 pts — Leila, Tom
- Auth token refresh: 3 pts — Leila
- Dashboard chart improvements: 13 pts — Tom
- Automated regression suite: 8 pts — Ana
- Performance monitoring alerts: 7 pts — Marcus
Priya reminded the team that the release is scheduled for July 11. All Sprint 14
work must be merged and QA-approved by July 9.
Meeting closed at 10:24.
"""
Running the Skill¶
When the agent activates the meeting-notes-summarizer skill, it will pause
twice to collect your preferences via HumanInputTool:
- Format —
bullet-pointsorprose - Detail level —
briefordetailed
The summary is then generated according to your choices.
result = await agent.run_with_skill(
"meeting-notes-summarizer",
prompt=f"Summarise the following meeting transcript:\n\n{TRANSCRIPT}",
)
print(result.content)
INFO (llm_agents_fs.LLMAgent) : 🚀 Starting task: This is a user-explicit skill activation. Call the from_scratch__use_skill tool with name='meeting-notes-summarizer'. Use exactly thi...[TRUNCATED]
INFO (llm_agents_fs.TaskHandler) : ⚙️ Processing Step: This is a user-explicit skill activation. Call the from_scratch__use_skill tool with name='meeting-notes-summarizer'. Use exactly ...[TRUNCATED]
INFO (llm_agents_fs.TaskHandler) : 🛠️ Executing Tool Call: from_scratch__use_skill
INFO (llm_agents_fs.TaskHandler) : ✅ Successful Tool Call: <skill_content name="meeting-notes-summarizer">
# Meeting Notes Summarizer
Produce a summary of a meeting transcript provided...[TRUNCATED]
INFO (llm_agents_fs.TaskHandler) : ✅ Step Result: I need to make the following tool-calls:
{
"id_": "0c458dea-bfae-4fb6-8643-32ce2e4dc870",
"tool_name": "from_scratch__human_inp...[TRUNCATED]
INFO (llm_agents_fs.TaskHandler) : 🧠 New Step: Execute the tool call to from_scratch__human_input with the prompt 'What format would you like the summary in?' and choices ['bullet-point...[TRUNCATED]
INFO (llm_agents_fs.TaskHandler) : ⚙️ Processing Step: Execute the tool call to from_scratch__human_input with the prompt 'What format would you like the summary in?' and choices ['bull...[TRUNCATED]
INFO (llm_agents_fs.TaskHandler) : 🛠️ Executing Tool Call: from_scratch__human_input
╭────────────────────────────────────────────────── Human Input ──────────────────────────────────────────────────╮ │ What format would you like the summary in? │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
> [bullet-points/prose]:
INFO (llm_agents_fs.TaskHandler) : ✅ Successful Tool Call: bullet-points
INFO (llm_agents_fs.TaskHandler) : ✅ Step Result: I need to make the following tool-calls:
{
"id_": "d1ccfed2-e10f-4afb-8e0b-094123909b89",
"tool_name": "from_scratch__human_inp...[TRUNCATED]
INFO (llm_agents_fs.TaskHandler) : 🧠 New Step: Execute the tool call to from_scratch__human_input with the prompt 'What level of detail?' and choices ['brief', 'detailed'] as specified ...[TRUNCATED]
INFO (llm_agents_fs.TaskHandler) : ⚙️ Processing Step: Execute the tool call to from_scratch__human_input with the prompt 'What level of detail?' and choices ['brief', 'detailed'] as sp...[TRUNCATED]
INFO (llm_agents_fs.TaskHandler) : 🛠️ Executing Tool Call: from_scratch__human_input
╭────────────────────────────────────────────────── Human Input ──────────────────────────────────────────────────╮ │ What level of detail? │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
> [brief/detailed]:
INFO (llm_agents_fs.TaskHandler) : ✅ Successful Tool Call: detailed
INFO (llm_agents_fs.TaskHandler) : ✅ Step Result: I now have both preferences from the user:
- Format preference: **bullet-points**
- Detail preference: **detailed**
According to the s...[TRUNCATED]
INFO (llm_agents_fs.TaskHandler) : No new step required.
INFO (llm_agents_fs.LLMAgent) : 🏁 Task completed: I now have both preferences from the user:
- Format preference: **bullet-points**
- Detail preference: **detailed**
According to th...[TRUNCATED]
I now have both preferences from the user:
- Format preference: **bullet-points**
- Detail preference: **detailed**
According to the skill instructions, for "bullet-points + detailed", I need to produce structured bullet points with sub-bullets covering all discussion topics, decisions, and action items.
Let me summarize the meeting transcript accordingly:
---
## Sprint 14 Planning Meeting Summary — 2026-06-27
### Meeting Overview
- **Attendees**: Priya (PM), Marcus (Lead Eng), Leila (Backend), Tom (Frontend), Ana (QA)
- **Meeting closed**: 10:24
### Sprint 13 Review
- **Velocity**: 42 points delivered against a target of 45
- **Rolled over stories**:
- Pagination refactor (8 pts)
- Email digest feature (5 pts)
- Both rolled-over stories are high priority for Sprint 14
### Key Discussion Topics & Decisions
- **Dependency Risk Identified**:
- Pagination refactor depends on a database migration scheduled for next Tuesday
- Risk: If migration slips, the refactor cannot be merged
- **Decision**: Move migration to Monday to de-risk
- **Task Assignments & Estimates**:
- Email digest feature:
- Leila: 3 days of backend work
- Tom: 1 day of frontend work (once Leila's API is ready)
- Ana will write the test plan today, ready for review by Wednesday
### Sprint 14 Commitments (44 points total)
- **Pagination refactor** (8 pts) — Marcus, Leila
- **Email digest** (5 pts) — Leila, Tom
- **Auth token refresh** (3 pts) — Leila
- **Dashboard chart improvements** (13 pts) — Tom
- **Automated regression suite** (8 pts) — Ana
- **Performance monitoring alerts** (7 pts) — Marcus
### Important Deadlines
- **Release date**: July 11
- **All Sprint 14 work must be merged and QA-approved by**: July 9
---
This summary covers all discussion topics, decisions made, and action items with their owners in a structured bullet-point format with detailed sub-bullets.