{"record":{"id":"6ebac61abdfad376","repo":"langchain-ai/deepagents","slug":"agent-hit-tool-approval-interrupt-limit","errorCode":null,"errorMessage":"agent hit tool approval interrupt limit","messagePattern":"agent hit tool approval interrupt limit","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"libs/talon/deepagents_talon/runtime.py","lineNumber":436,"sourceCode":"        if not callable(ainvoke):\n            msg = \"Deep Agents graph does not expose async invocation\"\n            raise TypeError(msg)\n        return cast(\"Callable[..., Awaitable[object]]\", ainvoke)\n\n    async def _invoke_until_unblocked(\n        self,\n        content: ModelContent,\n        request: AgentRequest,\n    ) -> object:\n        state = await self._invoke_with_retries(content, request.conversation_id)\n        for _ in range(DEFAULT_MAX_APPROVAL_ROUNDS):\n            interrupts = _interrupts_from_state(state)\n            if not interrupts:\n                return state\n            resume = await self._build_approval_resume(request, interrupts)\n            state = await self._resume_with_retries(resume, request.conversation_id)\n        msg = \"agent hit tool approval interrupt limit\"\n        raise RuntimeError(msg)\n\n    async def _build_approval_resume(\n        self,\n        request: AgentRequest,\n        interrupts: Sequence[object],\n    ) -> Command:\n        payload: dict[str, dict[str, list[dict[str, str]]]] = {}\n        for interrupt in interrupts:\n            interrupt_id = _interrupt_id(interrupt)\n            if interrupt_id is None:\n                logger.warning(\"Received tool approval interrupt without an id\")\n                continue\n            action_requests = _action_requests_from_interrupt(interrupt)\n            decision, reject_message, _resolution = await _approval_decision(\n                request,\n                interrupt_id,\n                action_requests,\n            )","sourceCodeStart":418,"sourceCodeEnd":454,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/talon/deepagents_talon/runtime.py#L418-L454","documentation":"_invoke_until_unblocked repeatedly resumes the graph after tool-approval interrupts, up to a fixed maximum number of iterations. When the agent keeps returning approval interrupts beyond that limit, this RuntimeError is raised to stop an infinite approve/resume cycle.","triggerScenarios":"A run where each resume produces new tool-approval interrupts — e.g. a tool that keeps requesting approval, or resume payloads that fail to satisfy the interrupt — until the iteration cap is reached inside _invoke_until_text.","commonSituations":"Human-in-the-loop flows where an approver keeps rejecting and the agent keeps re-requesting; approval callbacks wired so the resumed Command does not actually resolve the interrupts; a looping agent policy that retries the same disallowed tool.","solutions":["Increase the runtime's approval-interrupt limit if long approval chains are legitimate","Fix the approval handler/_build_approval_resume wiring so a resume actually satisfies the pending interrupts","Adjust the agent prompt/tools so it stops re-requesting approval for rejected actions"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    reply = await runtime.invoke(request)\nexcept RuntimeError as exc:\n    if \"tool approval interrupt limit\" in str(exc):\n        # surface to the human approver / pause the conversation\n        await escalate_to_human(request.conversation_id, exc)\n    else:\n        raise","preventionTips":["Ensure approval handlers actually resolve interrupts on resume (accept or reject) rather than no-op","Add agent prompt constraints against re-requesting rejected tools","Size the approval-interrupt limit to your real human-in-the-loop flow"],"tags":["human-in-the-loop","interrupts","limit"],"backgroundTag":"approval-loop-exceeded","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}