feat(I): I-APPR-LOOP — agent loop human-in-the-loop approval integration (require_approval + approval_tools params, ApprovalRequest creation, workstream notification, pause loop), 8 tests passing
This commit is contained in:
@@ -149,6 +149,8 @@ async def run_react_loop(
|
||||
trace_id: str | None = None,
|
||||
on_step: Callable | None = None,
|
||||
dry_run: bool = False,
|
||||
require_approval: bool = False,
|
||||
approval_tools: list[str] | None = None,
|
||||
) -> ReActResult:
|
||||
"""Execute a ReAct loop: LLM reasoning → tool execution → repeat.
|
||||
|
||||
@@ -371,6 +373,44 @@ async def run_react_loop(
|
||||
"arguments": args,
|
||||
}
|
||||
)
|
||||
elif require_approval and (approval_tools is None or tool_name in (approval_tools or [])):
|
||||
# I-APPR-LOOP: Human-in-the-Loop Approval
|
||||
# Create an ApprovalRequest and pause the loop
|
||||
try:
|
||||
from app.core.approval import create_approval_request
|
||||
from app.ai.agent_workstream import post_approval_request
|
||||
|
||||
approval = await create_approval_request(
|
||||
db=db,
|
||||
tenant_id=tenant_id,
|
||||
entity_type="agent_run",
|
||||
entity_id=agent_run_id or uuid.uuid4(),
|
||||
action=f"tool:{tool_name}",
|
||||
requested_by=user_id,
|
||||
requested_by_type="agent",
|
||||
)
|
||||
|
||||
# Post approval request to workstream
|
||||
if agent_run_id:
|
||||
await post_approval_request(
|
||||
db=db,
|
||||
tenant_id=tenant_id,
|
||||
agent_id=getattr(agent_definition, "id", uuid.uuid4()),
|
||||
approval_id=approval.id,
|
||||
action=f"Tool '{tool_name}' requires approval",
|
||||
details={"tool_name": tool_name, "arguments": args},
|
||||
)
|
||||
|
||||
# Pause the loop — return with waiting_for_approval status
|
||||
result.status = "waiting_for_approval"
|
||||
result.error = f"Tool '{tool_name}' requires human approval (request_id: {approval.id})"
|
||||
result.steps_taken = step_num
|
||||
result.final_content = f"I need approval to execute tool '{tool_name}'. Approval request {approval.id} has been created."
|
||||
logger.info("Agent loop paused for approval on tool '%s' (request: %s)", tool_name, approval.id)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.warning("Failed to create approval request for tool '%s': %s", tool_name, e)
|
||||
observation = json.dumps({"error": f"Approval required but failed to create request: {e}"})
|
||||
else:
|
||||
observation = await _execute_tool(tool_registry, tool_name, args, tool_context)
|
||||
observations.append(observation)
|
||||
|
||||
Reference in New Issue
Block a user