agent-runloop 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: agent-runloop
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Explicit, durable agent loop: validated tool calls, human approval, budgets, crash recovery, and composable router / waterfall / parallel / handoff / refine blocks.
5
5
  Project-URL: Homepage, https://github.com/kroq86/agent-loop
6
6
  Project-URL: Repository, https://github.com/kroq86/agent-loop
@@ -13,8 +13,8 @@ from agent_loop.compose import (
13
13
  Sequence, Step, Timeout, Verdict, chain_task, join_answers, majority_vote, step,
14
14
  )
15
15
  from agent_loop.loop import (
16
- AgentDecision, AgentResult, AgentStep, Budget, EventSink, FinalCheck, Status, ToolSpec, cancel_agent,
17
- current_call_id, recover_agent, resume_agent, run_agent, tool_error,
16
+ AgentDecision, AgentResult, AgentStep, Budget, EventSink, FinalCheck, Status, ToolSpec, ToolTimeout,
17
+ cancel_agent, current_call_id, recover_agent, resume_agent, run_agent, tool_error,
18
18
  )
19
19
  from agent_loop.runs import SqliteAgentRunStore
20
20
 
@@ -26,7 +26,7 @@ except PackageNotFoundError: # running from a source checkout
26
26
  __all__ = [
27
27
  "Agent", "AgentDecision", "AgentResult", "AgentStep", "Budget", "Context", "EventSink", "Fallback", "FinalCheck",
28
28
  "Handoff", "HandoffNote", "LLMBackend", "LLMClassifier", "LLMCritic", "Outcome", "Parallel", "Refine", "Router",
29
- "Sequence", "SqliteAgentRunStore", "Status", "Step", "Timeout", "ToolSpec", "Verdict", "cancel_agent",
29
+ "Sequence", "SqliteAgentRunStore", "Status", "Step", "Timeout", "ToolSpec", "ToolTimeout", "Verdict", "cancel_agent",
30
30
  "chain_task", "current_call_id", "hooks", "join_answers", "majority_vote", "recover_agent", "resume_agent",
31
31
  "run_agent", "step", "tool_error", "usage",
32
32
  ]
@@ -244,12 +244,24 @@ def tool_error(code: str, message: str) -> str:
244
244
  return json.dumps({"error": {"code": code, "message": message}})
245
245
 
246
246
 
247
+ class ToolTimeout(Exception):
248
+ """A tool exceeded its own `timeout_s`. Deliberately not a TimeoutError:
249
+ that one means the RUN's deadline, which ends the run. A slow tool is a
250
+ tool failure the model sees and can work around."""
251
+
252
+
247
253
  @trace
248
254
  async def execute_tool(spec: ToolSpec, args: BaseModel, trace_id: str) -> Any:
249
255
  """Separate traced node so trace.html shows each tool's validated
250
256
  arguments and full result, under the run_agent node."""
251
257
  trace.meta(tool=spec.name, arguments=args.model_dump(), tool_version=spec.version)
252
- return await asyncio.wait_for(spec.handler(args, trace_id), timeout=spec.timeout_s)
258
+ try:
259
+ return await asyncio.wait_for(spec.handler(args, trace_id), timeout=spec.timeout_s)
260
+ except TimeoutError:
261
+ # Only the tool's own timeout lands here: when the run's deadline
262
+ # fires, the wait is cancelled instead, and that surfaces as the
263
+ # run's TimeoutError one level up.
264
+ raise ToolTimeout(f"{spec.name} did not finish within its timeout of {spec.timeout_s}s") from None
253
265
 
254
266
 
255
267
  async def _execute(state: "_RunState", spec: ToolSpec, args: BaseModel, canonical: dict,
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "agent-runloop"
7
- version = "0.2.0"
7
+ version = "0.2.1"
8
8
  description = "Explicit, durable agent loop: validated tool calls, human approval, budgets, crash recovery, and composable router / waterfall / parallel / handoff / refine blocks."
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes