{"record":{"id":"3b3ab8201186fadf","repo":"langchain-ai/deepagents","slug":"project-hooks-cannot-execute-before-workspace-trus","errorCode":null,"errorMessage":"Project hooks cannot execute before workspace trust is granted","messagePattern":"Project hooks cannot execute before workspace trust is granted","errorType":"exception","errorClass":"PermissionError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/hooks/runtime.py","lineNumber":197,"sourceCode":"            agent_id: Optional subagent scope.\n        \"\"\"\n        self.transcripts.append_messages(thread_id, messages, agent_id=agent_id)\n\n    async def invoke(self, invocation: HookInvocation) -> HookDecision:\n        \"\"\"Materialize transcripts, execute matching handlers, and return a decision.\n\n        Args:\n            invocation: Domain lifecycle invocation.\n\n        Returns:\n            Event-specific decision with notices, sequences, and diagnostics.\n\n        Raises:\n            PermissionError: If project handlers were loaded without workspace trust.\n        \"\"\"\n        if self.project_hooks_loaded and not self.workspace_trusted:\n            msg = \"Project hooks cannot execute before workspace trust is granted\"\n            raise PermissionError(msg)\n        prepared = self.prepare_invocation(invocation)\n        return await self.engine.run(\n            prepared.invocation,\n            transcript_path=prepared.transcript_path,\n            agent_transcript_path=prepared.agent_transcript_path,\n            on_progress=self.presenter.update_progress,\n        )\n\n    def prepare_invocation(\n        self,\n        invocation: HookInvocation,\n    ) -> PreparedHookInvocation:\n        \"\"\"Materialize client-only transcript paths and revision identity.\n\n        Args:\n            invocation: Domain lifecycle invocation.\n\n        Returns:","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/hooks/runtime.py#L179-L215","documentation":"HooksRuntime.invoke refuses to run any hooks that come from project-level configuration when the workspace has not yet been marked trusted. The library treats project-supplied hook handlers as untrusted code, so executing them before an explicit trust grant would let a cloned repo run arbitrary code. It raises PermissionError defensively at the top of invoke.","triggerScenarios":"Calling runtime.invoke (public) while runtime.project_hooks_loaded is True and runtime.workspace_trusted is False — i.e. project hook handlers were loaded from the workspace but the user never approved trust for that workspace.","commonSituations":"Opening a cloned repository that ships .deepagents/hooks config and immediately invoking hooks programmatically; CI running in a fresh checkout where no trust prompt was answered; tests constructing a runtime with project hooks but skipping the trust step.","solutions":["Mark the workspace trusted before invoking: set runtime.workspace_trusted = True (or call the trust-approval API / trust_project_hooks flow for the project path).","If project hooks are not needed, load only user-level hooks so project_hooks_loaded stays False.","In automated environments, pre-seed the hooks trust store (hooks trust store JSON with the project path and current version) so trust is already granted.","Catch PermissionError and surface a trust prompt to the user instead of retrying."],"exampleFix":"// before\nruntime = HooksRuntime.from_config(project_config)\nawait runtime.invoke(invocation)  # PermissionError\n\n// after\nif not runtime.workspace_trusted:\n    trust_project_hooks(project_root)  # or prompt the user\nawait runtime.invoke(invocation)","handlingStrategy":"validation","validationCode":"if runtime.project_hooks_loaded and not runtime.workspace_trusted:\n    raise PermissionError(\"Trust this workspace before running project hooks\")\nawait runtime.invoke(invocation)","typeGuard":"def can_invoke(runtime) -> bool:\n    return not runtime.project_hooks_loaded or bool(runtime.workspace_trusted)","tryCatchPattern":"try:\n    await runtime.invoke(invocation)\nexcept PermissionError:\n    prompt_workspace_trust(runtime)  # then retry once","preventionTips":["Always run the trust-approval flow after cloning a repo that ships project hooks","In CI, pre-seed the hooks trust store before running hook-dependent steps","Check runtime.workspace_trusted before any invoke call","Prefer user-level hooks in untrusted environments"],"tags":["security","hooks","workspace-trust"],"backgroundTag":"untrusted-workspace-hooks","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}