66from typing import TYPE_CHECKING
77
88from operator_use .plugins .base import Plugin
9+ from operator_use .agent .hooks .events import HookEvent
910
1011if TYPE_CHECKING :
1112 from operator_use .agent .hooks import Hooks
2223 and the tool will run an isolated automation agent with its own context window (30-iteration budget). \
2324 The agent returns a summary of what was accomplished.
2425
26+ <perception>
27+ Before each desktop interaction, the current state of the desktop (active window, visible elements, \
28+ accessibility tree) is injected automatically into your context so you always have an up-to-date \
29+ view of the screen.
30+ </perception>
31+
32+ <tool_use>
33+ Use `computer_task` to delegate desktop goals. Describe the full goal in natural language — \
34+ the desktop subagent handles window focus, clicking, typing, and screen reading internally.
35+ </tool_use>
36+
37+ <execution_principles>
38+ - One `computer_task` call per distinct goal. Chain calls for multi-step workflows.
39+ - Prefer specific, outcome-oriented descriptions: "Save the document as report.docx" not "press Ctrl+S".
40+ - If a task fails, inspect the returned error and retry with a clearer description.
41+ </execution_principles>
42+
2543Example: "Open Notepad, type 'Hello World', save it as test.txt"
2644
2745The tool handles all the details of desktop state observation and action execution. You can chain \
@@ -69,11 +87,13 @@ def unregister_tools(self, registry: "ToolRegistry") -> None:
6987
7088 def register_hooks (self , hooks : "Hooks" ) -> None :
7189 self ._hooks = hooks
72- # Hooks are not registered to main agent (subagent manages its own state injection)
90+ if self ._enabled :
91+ hooks .register (HookEvent .BEFORE_LLM_CALL , self ._state_hook )
92+ hooks .register (HookEvent .AFTER_TOOL_CALL , self ._wait_for_ui_hook )
7393
7494 def unregister_hooks (self , hooks : "Hooks" ) -> None :
75- # No-op: hooks were never registered to main agent
76- pass
95+ hooks . unregister ( HookEvent . BEFORE_LLM_CALL , self . _state_hook )
96+ hooks . unregister ( HookEvent . AFTER_TOOL_CALL , self . _wait_for_ui_hook )
7797
7898 def attach_prompt (self , context : "Context" ) -> None :
7999 self ._context = context
@@ -114,6 +134,9 @@ def _init_sync(self) -> None:
114134 async def enable (self ) -> None :
115135 """Dynamically enable computer_use at runtime."""
116136 self ._enabled = True
137+ if self ._hooks is not None :
138+ self ._hooks .register (HookEvent .BEFORE_LLM_CALL , self ._state_hook )
139+ self ._hooks .register (HookEvent .AFTER_TOOL_CALL , self ._wait_for_ui_hook )
117140 if self ._registry is not None :
118141 for tool in self .get_tools ():
119142 if self ._registry .get (tool .name ) is None :
@@ -125,6 +148,8 @@ async def enable(self) -> None:
125148 async def disable (self ) -> None :
126149 """Dynamically disable computer_use at runtime."""
127150 self ._enabled = False
151+ if self ._hooks is not None :
152+ self .unregister_hooks (self ._hooks )
128153 if self ._registry is not None :
129154 self .unregister_tools (self ._registry )
130155 if self ._context is not None :
0 commit comments