-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathstructured_docs.json
More file actions
667 lines (667 loc) · 219 KB
/
structured_docs.json
File metadata and controls
667 lines (667 loc) · 219 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
{
"title": "deepwiki",
"description": "Documentation for deepwiki",
"content": {},
"metadata": {
"type": "root",
"path": "../data/OpenHands/deepwiki/docs",
"source": "deepwiki"
},
"subpages": [
{
"title": "Overview",
"description": null,
"content": {
"System Architecture": {
"High-Level Component Architecture": "```\ngraph TB\n subgraph \"User Interfaces\"\n WebUI[\"WebSession<br/>(session.py)\"]\n CLI[\"CLI Interface<br/>(cli/entry.py)\"]\n API[\"REST/WebSocket API<br/>(FastAPI)\"]\n end\n \n subgraph \"Core Orchestration\"\n AgentController[\"AgentController<br/>(agent_controller.py)\"]\n AgentSession[\"AgentSession<br/>(agent_session.py)\"]\n EventStream[\"EventStream<br/>(events/stream.py)\"]\n StateTracker[\"StateTracker<br/>(state/state_tracker.py)\"]\n end\n \n subgraph \"Agent System\"\n Agent[\"Agent<br/>(controller/agent.py)\"]\n Memory[\"Memory<br/>(memory/memory.py)\"]\n LLMRegistry[\"LLMRegistry<br/>(llm/llm_registry.py)\"]\n end\n \n subgraph \"Execution Environment\"\n Runtime[\"Runtime<br/>(runtime/base.py)\"]\n DockerRuntime[\"DockerRuntime<br/>(runtime/impl/docker)\"]\n Sandbox[\"ActionExecutionServer<br/>(runtime/server)\"]\n end\n \n subgraph \"Storage & Persistence\"\n FileStore[\"FileStore<br/>(storage/files.py)\"]\n ConversationStore[\"ConversationStore<br/>(storage/conversation)\"]\n EventStore[\"EventStore<br/>(events/event_store.py)\"]\n end\n \n WebUI --> AgentSession\n CLI --> AgentController\n API --> AgentSession\n \n AgentSession --> AgentController\n AgentController --> Agent\n AgentController --> EventStream\n AgentController --> StateTracker\n \n Agent --> Memory\n Agent --> LLMRegistry\n AgentController --> Runtime\n \n Runtime --> DockerRuntime\n Runtime --> Sandbox\n \n AgentSession --> FileStore\n EventStream --> EventStore\n StateTracker --> ConversationStore\n```\n\nSources: [openhands/server/session/session.py:40-112](), [openhands/controller/agent_controller.py:100-203](), [openhands/server/session/agent_session.py:42-89](), [openhands/core/main.py:51-96]()",
"Event-Driven Communication Flow": "```\ngraph TD\n subgraph \"Event Sources\"\n User[\"USER<br/>(MessageAction)\"]\n Agent[\"AGENT<br/>(Actions)\"]\n Environment[\"ENVIRONMENT<br/>(Observations)\"]\n end\n \n subgraph \"Event Processing\"\n EventStream[\"EventStream<br/>(sid, file_store, user_id)\"]\n EventStreamSubscriber[\"EventStreamSubscriber<br/>(AGENT_CONTROLLER, SERVER)\"]\n end\n \n subgraph \"Event Handlers\"\n AgentControllerHandler[\"AgentController.on_event<br/>(agent_controller.py:392)\"]\n WebSessionHandler[\"WebSession._on_event<br/>(session.py:314)\"]\n end\n \n subgraph \"Event Storage\"\n EventStore[\"EventStore<br/>(event_store.py)\"]\n FileStore[\"FileStore<br/>(files.py)\"]\n end\n \n User --> EventStream\n Agent --> EventStream\n Environment --> EventStream\n \n EventStream --> EventStreamSubscriber\n EventStreamSubscriber --> AgentControllerHandler\n EventStreamSubscriber --> WebSessionHandler\n \n EventStream --> EventStore\n EventStore --> FileStore\n```\n\nSources: [openhands/events/stream.py](), [openhands/server/session/session.py:311-330](), [openhands/controller/agent_controller.py:392-408]()"
},
"Core Components": {
"Agent Controller System": "The `AgentController` class serves as the primary orchestration component, managing agent lifecycle, state transitions, and action execution.\n\n| Component | File Path | Primary Responsibility |\n|-----------|-----------|----------------------|\n| `AgentController` | [openhands/controller/agent_controller.py:100-203]() | Agent orchestration and lifecycle management |\n| `State` | [openhands/controller/state/state.py]() | Agent state persistence and tracking |\n| `StateTracker` | [openhands/controller/state/state_tracker.py]() | State change monitoring and persistence |\n| `StuckDetector` | [openhands/controller/stuck.py]() | Agent loop detection and prevention |\n\nThe controller handles security analysis, confirmation mode, and error recovery through dedicated subsystems:\n\n```\ngraph LR\n subgraph \"AgentController Core\"\n Controller[\"AgentController\"]\n SecurityAnalyzer[\"SecurityAnalyzer<br/>(security/analyzer.py)\"]\n ConfirmationMode[\"confirmation_mode<br/>(boolean flag)\"]\n end\n \n subgraph \"State Management\"\n State[\"State<br/>(agent_state, iterations, budget)\"]\n StateTracker[\"StateTracker<br/>(sid, file_store, user_id)\"]\n StuckDetector[\"StuckDetector<br/>(state)\"]\n end\n \n Controller --> SecurityAnalyzer\n Controller --> ConfirmationMode\n Controller --> State\n Controller --> StateTracker\n Controller --> StuckDetector\n```\n\nSources: [openhands/controller/agent_controller.py:100-203](), [openhands/controller/state/state_tracker.py]()",
"Session Management Architecture": "OpenHands uses a dual-session architecture separating web connectivity from agent execution:\n\n```\ngraph TD\n subgraph \"Session Layer\"\n WebSession[\"WebSession<br/>(sid, sio, config, llm_registry)\"]\n AgentSession[\"AgentSession<br/>(sid, file_store, llm_registry)\"]\n end\n \n subgraph \"Communication\"\n SocketIO[\"socketio.AsyncServer\"]\n EventStreamSubscriber[\"EventStreamSubscriber.SERVER\"]\n end\n \n subgraph \"Agent Execution\"\n AgentController[\"AgentController\"]\n Runtime[\"Runtime\"]\n Agent[\"Agent\"]\n end\n \n WebSession --> AgentSession\n WebSession --> SocketIO\n WebSession --> EventStreamSubscriber\n \n AgentSession --> AgentController\n AgentSession --> Runtime\n AgentSession --> Agent\n```\n\nSources: [openhands/server/session/session.py:74-112](), [openhands/server/session/agent_session.py:64-89]()",
"Runtime Environment System": "The runtime system provides sandboxed execution environments with multiple implementation options:\n\n| Runtime Type | Implementation | Use Case |\n|--------------|----------------|----------|\n| `DockerRuntime` | [openhands/runtime/impl/docker]() | Local Docker-based sandbox |\n| `RemoteRuntime` | [openhands/runtime/impl/remote]() | Remote execution environment |\n| `LocalRuntime` | [openhands/runtime/impl/local]() | Direct local execution |\n| `E2BRuntime` | [openhands/runtime/impl/e2b]() | E2B cloud sandbox |\n\nThe runtime architecture supports pluggable sandbox backends:\n\n```\ngraph TB\n subgraph \"Runtime Interface\"\n BaseRuntime[\"Runtime<br/>(base.py)\"]\n RuntimeConfig[\"RuntimeConfig<br/>(config)\"]\n end\n \n subgraph \"Runtime Implementations\"\n DockerRuntime[\"DockerRuntime<br/>(impl/docker/docker_runtime.py)\"]\n RemoteRuntime[\"RemoteRuntime<br/>(impl/remote/remote_runtime.py)\"]\n LocalRuntime[\"LocalRuntime<br/>(impl/local/local_runtime.py)\"]\n E2BRuntime[\"E2BRuntime<br/>(impl/e2b/e2b_runtime.py)\"]\n end\n \n subgraph \"Execution Server\"\n ActionExecutionServer[\"ActionExecutionServer<br/>(server/action_execution.py)\"]\n SandboxPlugins[\"SandboxPlugins<br/>(plugins/)\"]\n end\n \n BaseRuntime --> DockerRuntime\n BaseRuntime --> RemoteRuntime\n BaseRuntime --> LocalRuntime\n BaseRuntime --> E2BRuntime\n \n DockerRuntime --> ActionExecutionServer\n ActionExecutionServer --> SandboxPlugins\n```\n\nSources: [openhands/runtime/base.py](), [openhands/runtime/impl/docker](), [openhands/core/setup.py:35-89]()",
"LLM Integration Framework": "OpenHands supports multiple LLM providers through a unified registry system built on `litellm`:\n\n```\ngraph LR\n subgraph \"LLM Registry\"\n LLMRegistry[\"LLMRegistry<br/>(llm_registry.py)\"]\n LLMConfig[\"LLMConfig<br/>(config/llm_config.py)\"]\n LiteLLM[\"LiteLLM Backend\"]\n end\n \n subgraph \"LLM Providers\"\n OpenAI[\"OpenAI<br/>(openai)\"]\n Anthropic[\"Anthropic<br/>(anthropic)\"]\n Google[\"Google<br/>(google-genai)\"]\n Local[\"Local Models<br/>(ollama/vllm)\"]\n end\n \n subgraph \"Configuration\"\n AgentToLLMConfig[\"agent_to_llm_config<br/>(dict[str, LLMConfig])\"]\n OpenHandsConfig[\"OpenHandsConfig<br/>(core/config.py)\"]\n end\n \n LLMRegistry --> LLMConfig\n LLMRegistry --> LiteLLM\n LiteLLM --> OpenAI\n LiteLLM --> Anthropic\n LiteLLM --> Google\n LiteLLM --> Local\n \n OpenHandsConfig --> AgentToLLMConfig\n AgentToLLMConfig --> LLMConfig\n```\n\nSources: [openhands/llm/llm_registry.py](), [pyproject.toml:29-30](), [openhands/core/config/llm_config.py]()"
},
"Key Execution Workflows": {
"Agent Task Execution Flow": "The primary execution workflow orchestrates user input through agent processing to action execution:\n\n```\ngraph TD\n UserMessage[\"MessageAction<br/>(EventSource.USER)\"] --> EventStream\n EventStream --> AgentControllerOnEvent[\"AgentController.on_event<br/>(agent_controller.py:392)\"]\n AgentControllerOnEvent --> ShouldStep[\"should_step()<br/>(agent_controller.py:392)\"]\n ShouldStep --> Step[\"_step()<br/>(agent_controller.py:440)\"]\n \n Step --> AgentStep[\"agent.step()<br/>(controller/agent.py)\"]\n AgentStep --> LLMCall[\"LLM.completion()<br/>(llm/)\"]\n LLMCall --> ActionParsing[\"parse_response()<br/>(agent/)\"]\n ActionParsing --> SecurityAnalysis[\"_handle_security_analyzer()<br/>(agent_controller.py:204)\"]\n \n SecurityAnalysis --> RuntimeExecution[\"runtime.run_action()<br/>(runtime/)\"]\n RuntimeExecution --> ObservationGeneration[\"Observation<br/>(events/observation/)\"]\n ObservationGeneration --> EventStream\n```\n\nSources: [openhands/controller/agent_controller.py:392-408](), [openhands/controller/agent_controller.py:440-500](), [openhands/controller/agent_controller.py:204-243]()",
"Configuration and Initialization": "OpenHands uses a layered configuration system combining TOML files, environment variables, and runtime settings:\n\n| Configuration Source | File Path | Priority |\n|---------------------|-----------|----------|\n| Environment Variables | System environment | Highest |\n| `config.toml` | [config.toml]() | Medium |\n| Default Values | [openhands/core/config/]() | Lowest |\n\nThe initialization process follows this sequence:\n\n```\ngraph TD\n ConfigParsing[\"parse_arguments()<br/>(core/config.py)\"] --> SetupConfig[\"setup_config_from_args()<br/>(core/config.py)\"]\n SetupConfig --> CreateAgent[\"create_agent()<br/>(core/setup.py:150)\"]\n CreateAgent --> CreateRuntime[\"create_runtime()<br/>(core/setup.py:35)\"]\n CreateRuntime --> CreateMemory[\"create_memory()<br/>(core/setup.py:200)\"]\n CreateMemory --> CreateController[\"create_controller()<br/>(core/setup.py:240)\"]\n CreateController --> RunAgent[\"run_agent_until_done()<br/>(core/loop.py)\"]\n```\n\nSources: [openhands/core/main.py:51-96](), [openhands/core/setup.py:35-89](), [openhands/core/config/]()\n\nThe system supports multiple deployment modes including local development, Docker containers, and cloud-based execution through this unified configuration and initialization framework.\n\nSources: [README.md:53-127](), [pyproject.toml:1-199](), [frontend/package.json:1-151]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
},
{
"title": "Getting Started",
"description": null,
"content": {
"Installation Options Overview": "OpenHands offers multiple installation methods to accommodate different user needs and environments:\n\n```\ngraph TD\n subgraph \"Installation Methods\"\n CLOUD[\"OpenHands Cloud<br/>(SaaS Solution)\"]\n CLI[\"CLI Launcher<br/>(Recommended)\"]\n DOCKER[\"Docker<br/>(Containerized)\"]\n DEV[\"Development Setup<br/>(Source Code)\"]\n end\n \n subgraph \"Requirements\"\n PYTHON[\"Python 3.12+\"]\n UV[\"uv Package Manager\"]\n DOCKER_ENGINE[\"Docker Engine\"]\n NODEJS[\"Node.js 22+\"]\n POETRY[\"Poetry 1.8+\"]\n end\n \n CLOUD -.->|\"No local setup required\"| NONE[\"No Dependencies\"]\n CLI --> UV\n CLI --> PYTHON\n DOCKER --> DOCKER_ENGINE\n DEV --> PYTHON\n DEV --> NODEJS\n DEV --> POETRY\n DEV --> DOCKER_ENGINE\n \n style CLOUD fill:#e1f5fe\n style CLI fill:#f3e5f5\n style DOCKER fill:#fff3e0\n style DEV fill:#e8f5e8\n```\n\n**Installation Method Comparison**\n\n| Method | Use Case | Setup Time | Flexibility | Resource Usage |\n|--------|----------|------------|-------------|----------------|\n| Cloud | Quick evaluation, no local setup | < 5 minutes | Limited | Remote |\n| CLI Launcher | General usage, isolated environment | 5-10 minutes | High | Low |\n| Docker | Containerized deployment | 10-15 minutes | Medium | Medium |\n| Development | Contributing, customization | 15-30 minutes | Maximum | High |\n\nSources: [README.md:49-131](), [Development.md:11-22]()",
"Cloud Installation": "The quickest way to get started is with OpenHands Cloud, which requires no local installation:\n\n['Visit [OpenHands Cloud](https://app.all-hands.dev)', 'Sign up for an account', 'New users receive $20 in free credits', 'Select your preferred LLM provider and configure API keys in the web interface']\n\nSources: [README.md:49-51]()",
"CLI Launcher Installation (Recommended)": {
"Prerequisites": "Install `uv` package manager following the [official installation guide](https://docs.astral.sh/uv/getting-started/installation/):\n\n```\n# Example installation methods (choose one)\ncurl -LsSf https://astral.sh/uv/install.sh | sh\n# or\npip install uv\n# or\npipx install uv\n```",
"Installation and Usage": "```\n# Launch the GUI server\nuvx --python 3.12 --from openhands-ai openhands serve\n\n# Launch the CLI interface \nuvx --python 3.12 --from openhands-ai openhands\n```\n\nThe GUI interface will be available at `http://localhost:3000`.\n\nSources: [README.md:55-72]()"
},
"Docker Installation": {
"Pull Required Images": "```\ndocker pull docker.all-hands.dev/all-hands-ai/runtime:0.56-nikolaik\n```",
"Run OpenHands Container": "```\ndocker run -it --rm --pull=always \\\n -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.56-nikolaik \\\n -e LOG_ALL_EVENTS=true \\\n -v /var/run/docker.sock:/var/run/docker.sock \\\n -v ~/.openhands:/.openhands \\\n -p 3000:3000 \\\n --add-host host.docker.internal:host-gateway \\\n --name openhands-app \\\n docker.all-hands.dev/all-hands-ai/openhands:0.56\n```",
"Docker Environment Configuration": "The container accepts several environment variables for configuration:\n\n['`SANDBOX_RUNTIME_CONTAINER_IMAGE`: Runtime container image', '`SANDBOX_USER_ID`: User ID for sandbox execution', '`WORKSPACE_MOUNT_PATH`: Path to workspace directory', '`LOG_ALL_EVENTS`: Enable comprehensive event logging']\n\nSources: [README.md:76-96](), [docker-compose.yml:8-13]()"
},
"Development Installation": {
"System Requirements": "```\ngraph LR\n subgraph \"Core Requirements\"\n OS[\"Linux/macOS/WSL<br/>(Ubuntu ≥22.04)\"]\n PYTHON[\"Python 3.12\"]\n NODE[\"Node.js ≥22.x\"]\n DOCKER[\"Docker Engine\"]\n POETRY[\"Poetry ≥1.8\"]\n end\n \n subgraph \"Platform-Specific\"\n UBUNTU[\"Ubuntu:<br/>build-essential<br/>python3.12-dev\"]\n WSL[\"WSL:<br/>netcat\"]\n MACOS[\"macOS:<br/>Docker Desktop\"]\n end\n \n subgraph \"Build System\"\n MAKE[\"Make\"]\n GIT[\"Git\"]\n TMUX[\"tmux (optional)\"]\n end\n \n OS --> UBUNTU\n OS --> WSL \n OS --> MACOS\n```\n\nSources: [Development.md:11-21]()",
"Installation Steps": [
"**Clone the repository:**",
"```\ngit clone https://github.com/All-Hands-AI/OpenHands.git\ncd OpenHands\n```",
"**Build the project:**",
"```\nmake build\n```",
"This command orchestrates:",
[
"Dependency verification via `make check-dependencies`",
"Python dependency installation via `make install-python-dependencies`",
"Frontend dependency installation via `make install-frontend-dependencies`",
"Pre-commit hook installation via `make install-pre-commit-hooks`",
"Frontend build via `make build-frontend`"
],
"**Configure the language model:**",
"```\nmake setup-config\n```",
"**Start the application:**",
"```\nmake run\n```"
]
},
"Configuration System Architecture": {
"Configuration File Structure": "The primary configuration file follows TOML format with these main sections:\n\n```\n[core]\nworkspace_base = \"./workspace\"\nruntime = \"docker\"\ndefault_agent = \"CodeActAgent\"\nmax_iterations = 500\n\n[llm]\nmodel = \"claude-sonnet-4-20250514\"\napi_key = \"your-api-key\"\ntemperature = 0.0\nmax_output_tokens = 4096\n\n[agent]\nenable_browsing = true\nenable_jupyter = true\nenable_cmd = true\n\n[sandbox]\ntimeout = 120\n```\n\nSources: [config.template.toml:9-75](), [openhands/core/config/utils.py:138-200]()",
"Configuration Class Hierarchy": "```\nclassDiagram\n class OpenHandsConfig {\n +workspace_base: str\n +runtime: str\n +default_agent: str\n +max_iterations: int\n +get_llm_config() LLMConfig\n +get_agent_config() AgentConfig\n }\n \n class LLMConfig {\n +model: str\n +api_key: SecretStr\n +base_url: str\n +temperature: float\n +max_output_tokens: int\n +from_toml_section() dict\n }\n \n class AgentConfig {\n +enable_browsing: bool\n +enable_jupyter: bool \n +enable_cmd: bool\n +llm_config: str\n +system_prompt_filename: str\n +from_toml_section() dict\n }\n \n class SandboxConfig {\n +timeout: int\n +runtime_container_image: str\n +user_id: int\n +mount_workspace: bool\n }\n \n OpenHandsConfig --> LLMConfig\n OpenHandsConfig --> AgentConfig\n OpenHandsConfig --> SandboxConfig\n```\n\nSources: [openhands/core/config/openhands_config.py](), [openhands/core/config/llm_config.py:12-51](), [openhands/core/config/agent_config.py:15-65]()"
},
"Initial Configuration": {
"LLM Provider Setup": "OpenHands supports multiple LLM providers through the `litellm` library. The recommended configuration process:\n\n['**Interactive Configuration:**', '```\\nmake setup-config\\n```', 'This prompts for:', ['Workspace directory path', 'LLM model name', 'API key', 'Base URL (for local LLMs)'], '**Manual Configuration:**\\nCreate `config.toml` in the project root:', '```\\n[core]\\nworkspace_base = \"./workspace\"\\n\\n[llm]\\nmodel = \"anthropic/claude-sonnet-4-20250514\"\\napi_key = \"your-anthropic-api-key\"\\n```', '**Environment Variable Configuration:**', '```\\nexport LLM_MODEL=\"anthropic/claude-sonnet-4-20250514\"\\nexport LLM_API_KEY=\"your-api-key\"\\nexport LLM_BASE_URL=\"https://api.anthropic.com\"\\n```']",
"Recommended LLM Models": "| Provider | Model | Performance | Cost |\n|----------|-------|-------------|------|\n| Anthropic | `claude-sonnet-4-20250514` | Excellent | High |\n| OpenAI | `gpt-4o` | Excellent | High |\n| OpenAI | `gpt-4o-mini` | Good | Low |\n| Google | `gemini-2.5-pro` | Excellent | Medium |\n\nSources: [README.md:105-107](), [Makefile:301-325](), [openhands/core/config/utils.py:127-135]()"
},
"Basic Usage Patterns": {
"Starting OpenHands": "After installation and configuration, start OpenHands using your preferred method:\n\n```\n# Development mode (with live reloading)\nmake run\n\n# Individual server startup\nmake start-backend # Port 3000\nmake start-frontend # Port 3001\n\n# Docker mode\nmake docker-run\n\n# Production mode\nuvx --python 3.12 --from openhands-ai openhands serve\n```",
"Web Interface Access": "The web interface provides the primary interaction method:\n\n['Navigate to `http://localhost:3000`', 'Configure your LLM provider in the settings', 'Start a new conversation', 'Provide instructions in natural language']",
"CLI Interface Access": "For headless operation:\n\n```\n# Interactive CLI mode\nuvx --python 3.12 --from openhands-ai openhands\n\n# Direct command execution\nopenhands --task \"Fix the bug in main.py\" --model gpt-4o\n```\n\nSources: [Development.md:82-89](), [Makefile:248-283]()",
"Workspace Configuration": "OpenHands operates within a designated workspace directory:\n\n```\ngraph LR\n subgraph \"Host System\"\n HOST_WS[\"Host Workspace<br/>~/.openhands/workspace\"]\n CONFIG[\"config.toml<br/>workspace_base\"]\n end\n \n subgraph \"Container Environment\"\n SANDBOX_WS[\"Sandbox Workspace<br/>/workspace\"]\n MOUNT[\"Volume Mount\"]\n end\n \n subgraph \"Agent Operations\"\n READ[\"File Reading\"]\n WRITE[\"File Writing\"] \n EXEC[\"Code Execution\"]\n end\n \n CONFIG --> HOST_WS\n HOST_WS --> MOUNT\n MOUNT --> SANDBOX_WS\n SANDBOX_WS --> READ\n SANDBOX_WS --> WRITE\n SANDBOX_WS --> EXEC\n```\n\nThe workspace configuration controls:\n\n['File access permissions', 'Code execution environment', 'Persistent storage location', 'Security boundaries']\n\nSources: [config.template.toml:15-16](), [openhands/core/config/sandbox_config.py]()"
},
"Build System Overview": "The OpenHands build system orchestrates multiple components through Make targets:\n\n```\ngraph TB\n subgraph \"Build Dependencies\"\n CHECK_DEPS[\"check-dependencies<br/>(System validation)\"]\n CHECK_PYTHON[\"check-python<br/>(Python 3.12 verification)\"]\n CHECK_NODE[\"check-nodejs<br/>(Node.js ≥22 verification)\"]\n CHECK_DOCKER[\"check-docker<br/>(Docker availability)\"]\n CHECK_POETRY[\"check-poetry<br/>(Poetry ≥1.8 verification)\"]\n end\n \n subgraph \"Installation Phase\"\n INSTALL_PY[\"install-python-dependencies<br/>(Poetry install)\"]\n INSTALL_FE[\"install-frontend-dependencies<br/>(npm install)\"]\n INSTALL_HOOKS[\"install-pre-commit-hooks<br/>(Code quality setup)\"]\n end\n \n subgraph \"Build Phase\"\n BUILD_FE[\"build-frontend<br/>(npm run build)\"]\n BUILD_COMPLETE[\"Build Complete\"]\n end\n \n CHECK_DEPS --> CHECK_PYTHON\n CHECK_DEPS --> CHECK_NODE\n CHECK_DEPS --> CHECK_DOCKER\n CHECK_DEPS --> CHECK_POETRY\n \n CHECK_PYTHON --> INSTALL_PY\n CHECK_NODE --> INSTALL_FE\n INSTALL_PY --> INSTALL_HOOKS\n \n INSTALL_FE --> BUILD_FE\n BUILD_FE --> BUILD_COMPLETE\n```\n\nKey build targets include:\n\n['`make build`: Complete build process', '`make check-dependencies`: Verify system requirements', '`make install-python-dependencies`: Install Python packages via Poetry', '`make install-frontend-dependencies`: Install Node.js packages via npm', '`make lint`: Run code quality checks', '`make test`: Execute test suites']\n\nSources: [Makefile:24-45](), [Makefile:139-175](), [Makefile:177-183]()"
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
},
{
"title": "Agent System",
"description": null,
"content": {
"Architecture Overview": {
"Core Components Architecture": "```\ngraph TB\n subgraph \"Session Management Layer\"\n WebSession[\"WebSession<br/>(session.py)\"]\n AgentSession[\"AgentSession<br/>(agent_session.py)\"]\n ConversationManager[\"ConversationManager<br/>(conversation_manager.py)\"]\n end\n \n subgraph \"Agent Orchestration Layer\"\n AgentController[\"AgentController<br/>(agent_controller.py)\"]\n StateTracker[\"StateTracker<br/>(state_tracker.py)\"]\n Agent[\"Agent<br/>(agent.py)\"]\n Memory[\"Memory<br/>(memory.py)\"]\n end\n \n subgraph \"Communication Layer\"\n EventStream[\"EventStream<br/>(stream.py)\"]\n EventSubscriber[\"EventStreamSubscriber<br/>(stream.py)\"]\n end\n \n subgraph \"State & Persistence\"\n State[\"State<br/>(state.py)\"]\n FileStore[\"FileStore<br/>(files.py)\"]\n ConversationStats[\"ConversationStats<br/>(conversation_stats.py)\"]\n end\n \n WebSession --> AgentSession\n AgentSession --> AgentController\n ConversationManager --> WebSession\n \n AgentController --> StateTracker\n AgentController --> Agent\n AgentController --> Memory\n AgentController --> EventStream\n \n StateTracker --> State\n EventStream --> EventSubscriber\n State --> FileStore\n AgentController --> ConversationStats\n \n style AgentController fill:#ffeeee\n style EventStream fill:#eeffee\n style State fill:#eeeeff\n```\n\nSources: [openhands/controller/agent_controller.py:100-200](), [openhands/server/session/session.py:40-75](), [openhands/server/session/agent_session.py:42-88](), [openhands/server/conversation_manager/conversation_manager.py:20-50]()"
},
"Agent Controller & State Management": {
"AgentController Core Components": "```\ngraph TD\n subgraph \"AgentController Class\"\n controller_init[\"__init__()<br/>Initialize controller\"]\n step_method[\"step()<br/>Execute agent step\"]\n on_event[\"on_event()<br/>Handle incoming events\"]\n set_agent_state[\"set_agent_state_to()<br/>Update agent state\"]\n handle_action[\"_handle_action()<br/>Process agent actions\"]\n handle_observation[\"_handle_observation()<br/>Process observations\"]\n end\n \n subgraph \"State Management\"\n State_restore[\"State.restore_from_session()\"]\n state_save[\"state.save_to_session()\"]\n StateTracker_class[\"StateTracker<br/>run_control_flags()\"]\n StuckDetector[\"StuckDetector<br/>_is_stuck()\"]\n end\n \n subgraph \"Event Processing\"\n should_step[\"should_step()<br/>Determine if agent should act\"]\n react_to_exception[\"_react_to_exception()<br/>Handle errors\"]\n reset_method[\"_reset()<br/>Reset agent state\"]\n end\n \n controller_init --> State_restore\n step_method --> should_step\n on_event --> handle_action\n on_event --> handle_observation\n step_method --> StateTracker_class\n step_method --> StuckDetector\n set_agent_state --> state_save\n step_method --> react_to_exception\n set_agent_state --> reset_method\n \n style step_method fill:#ffeeee\n style on_event fill:#eeffee\n style State_restore fill:#eeeeff\n```\n\nSources: [openhands/controller/agent_controller.py:100-200](), [openhands/controller/agent_controller.py:358-390](), [openhands/controller/agent_controller.py:433-493](), [openhands/controller/state/state_tracker.py]()",
"Agent State Lifecycle": "The system manages agent states through the `AgentState` enum, transitioning between states based on events and conditions:\n\n| State | Description | Triggers |\n|-------|-------------|----------|\n| `LOADING` | Agent initialization | Session startup |\n| `AWAITING_USER_INPUT` | Waiting for user message | Agent requests input |\n| `RUNNING` | Actively processing | User message received |\n| `USER_CONFIRMED` | Action confirmed | User approval in confirmation mode |\n| `USER_REJECTED` | Action rejected | User rejection in confirmation mode |\n| `FINISHED` | Task completed | `AgentFinishAction` |\n| `STOPPED` | Manual stop | User interruption |\n| `ERROR` | Error occurred | Exception handling |\n\nSources: [openhands/controller/agent_controller.py:631-683](), [openhands/core/schema/agent.py]()"
},
"Session Management": {
"Session Architecture Flow": "```\ngraph LR\n subgraph \"Client Layer\"\n WebClient[\"Web Client<br/>(React Frontend)\"]\n SocketIO[\"Socket.IO<br/>Connection\"]\n end\n \n subgraph \"Session Layer\"\n WebSession_manage[\"WebSession<br/>sio: socketio.AsyncServer<br/>agent_session: AgentSession\"]\n ConversationManager_concrete[\"ConversationManager<br/>_local_agent_loops_by_sid<br/>_local_connection_id_to_session_id\"]\n end\n \n subgraph \"Agent Layer\" \n AgentSession_manage[\"AgentSession<br/>controller: AgentController<br/>runtime: Runtime<br/>memory: Memory\"]\n AgentController_manage[\"AgentController<br/>agent: Agent<br/>event_stream: EventStream<br/>state: State\"]\n end\n \n WebClient --> SocketIO\n SocketIO --> WebSession_manage\n ConversationManager_concrete --> WebSession_manage\n WebSession_manage --> AgentSession_manage\n AgentSession_manage --> AgentController_manage\n \n style WebSession_manage fill:#ffeeee\n style AgentSession_manage fill:#eeffee\n style ConversationManager_concrete fill:#eeeeff\n```\n\nSources: [openhands/server/session/session.py:74-112](), [openhands/server/session/agent_session.py:64-88](), [openhands/server/conversation_manager/standalone_conversation_manager.py:53-77]()",
"Session Initialization Process": "The session initialization follows a specific sequence to set up the complete agent environment:\n\n['**WebSession Creation**: Socket.IO connection established', '**Agent Configuration**: LLM config and agent type selection ', '**Runtime Initialization**: Sandbox environment setup', '**Memory Creation**: Context and microagent loading', '**Controller Setup**: Agent controller with state restoration', '**Event Stream Activation**: Begin event processing']\n\nSources: [openhands/server/session/session.py:132-305](), [openhands/server/session/agent_session.py:90-223]()"
},
"Event-Driven Communication": {
"Event Flow Architecture": "```\ngraph TB\n subgraph \"Event Sources\"\n User[\"USER<br/>(MessageAction)\"]\n Agent_src[\"AGENT<br/>(Actions/Responses)\"]\n Environment[\"ENVIRONMENT<br/>(Observations)\"]\n end\n \n subgraph \"EventStream Core\"\n EventStream_class[\"EventStream<br/>add_event()<br/>subscribe()<br/>get_events()\"]\n EventStreamSubscriber_enum[\"EventStreamSubscriber<br/>AGENT_CONTROLLER<br/>SERVER<br/>MAIN\"]\n end\n \n subgraph \"Event Processors\"\n AgentController_proc[\"AgentController<br/>on_event()<br/>should_step()\"]\n WebSession_proc[\"WebSession<br/>on_event()<br/>dispatch()\"]\n MainLoop[\"Main Loop<br/>run_controller()\"]\n end\n \n subgraph \"Event Types\"\n Actions[\"Actions<br/>MessageAction<br/>CmdRunAction<br/>FileEditAction\"]\n Observations[\"Observations<br/>CmdOutputObservation<br/>AgentStateChangedObservation\"]\n end\n \n User --> EventStream_class\n Agent_src --> EventStream_class\n Environment --> EventStream_class\n \n EventStream_class --> EventStreamSubscriber_enum\n EventStreamSubscriber_enum --> AgentController_proc\n EventStreamSubscriber_enum --> WebSession_proc\n EventStreamSubscriber_enum --> MainLoop\n \n EventStream_class --> Actions\n EventStream_class --> Observations\n \n style EventStream_class fill:#ffeeee\n style EventStreamSubscriber_enum fill:#eeffee\n```\n\nSources: [openhands/events/stream.py](), [openhands/controller/agent_controller.py:433-493](), [openhands/server/session/session.py:311-352](), [openhands/events/action/__init__.py](), [openhands/events/observation/__init__.py]()",
"Event Processing Pipeline": "Each event follows a consistent processing pipeline:\n\n['**Event Addition**: Added to `EventStream` with source attribution', '**Subscriber Notification**: All registered subscribers receive event', '**Filtering**: Each subscriber applies `should_step()` logic', '**Processing**: Relevant subscribers process the event', '**State Updates**: Agent state and conversation state updated', '**Response Generation**: New events may be generated as responses']\n\nSources: [openhands/controller/agent_controller.py:392-431](), [openhands/controller/agent_controller.py:467-493]()"
},
"Agent Lifecycle Management": {
"Agent Execution Loop": "```\ngraph TD\n subgraph \"Initialization Phase\"\n create_agent[\"create_agent()<br/>(setup.py)\"]\n create_runtime[\"create_runtime()<br/>(setup.py)\"]\n create_memory[\"create_memory()<br/>(setup.py)\"]\n create_controller[\"create_controller()<br/>(setup.py)\"]\n end\n \n subgraph \"Execution Loop\"\n wait_event[\"Wait for Event<br/>(EventStream)\"]\n should_step_check[\"should_step()<br/>(agent_controller.py)\"]\n agent_step[\"agent.step()<br/>(Agent.step())\"]\n execute_action[\"Execute Action<br/>(Runtime)\"]\n observe_result[\"Generate Observation<br/>(Runtime/Environment)\"]\n end\n \n subgraph \"State Management\"\n check_limits[\"run_control_flags()<br/>(StateTracker)\"]\n stuck_detection[\"_is_stuck()<br/>(StuckDetector)\"]\n save_state[\"save_state()<br/>(State)\"]\n end\n \n subgraph \"Error Handling\"\n catch_exception[\"_react_to_exception()<br/>(agent_controller.py)\"]\n set_error_state[\"set_agent_state_to(ERROR)<br/>(agent_controller.py)\"]\n reset_agent[\"_reset()<br/>(agent_controller.py)\"]\n end\n \n create_agent --> create_runtime\n create_runtime --> create_memory\n create_memory --> create_controller\n create_controller --> wait_event\n \n wait_event --> should_step_check\n should_step_check -->|Yes| check_limits\n check_limits -->|Pass| stuck_detection\n stuck_detection -->|Not stuck| agent_step\n agent_step --> execute_action\n execute_action --> observe_result\n observe_result --> save_state\n save_state --> wait_event\n \n check_limits -->|Fail| catch_exception\n stuck_detection -->|Stuck| catch_exception\n agent_step -->|Exception| catch_exception\n catch_exception --> set_error_state\n set_error_state --> reset_agent\n \n should_step_check -->|No| wait_event\n \n style agent_step fill:#ffeeee\n style check_limits fill:#eeffee\n style catch_exception fill:#ffcccc\n```\n\nSources: [openhands/core/setup.py:202-243](), [openhands/controller/agent_controller.py:821-887](), [openhands/controller/agent_controller.py:302-391](), [openhands/controller/stuck.py]()"
},
"Memory & Context Management": {
"Memory Architecture": "```\ngraph TB\n subgraph \"Memory Class Components\"\n Memory_init[\"Memory<br/>__init__()<br/>event_stream: EventStream<br/>sid: str\"]\n runtime_info[\"set_runtime_info()<br/>Available hosts<br/>Working directory\"]\n repo_info[\"set_repository_info()<br/>Repository details<br/>Branch information\"]\n microagents[\"load_user_workspace_microagents()<br/>Custom agent tools\"]\n conversation_instructions[\"set_conversation_instructions()<br/>User-provided context\"]\n end\n \n subgraph \"Context Sources\"\n EventStream_memory[\"EventStream<br/>Conversation history\"]\n Runtime_memory[\"Runtime<br/>System information<br/>Available tools\"]\n Repository[\"Repository<br/>Project context<br/>File structure\"]\n Microagents[\"Microagents<br/>Custom tools<br/>Specialized capabilities\"]\n UserSecrets[\"UserSecrets<br/>API keys<br/>Configuration\"]\n end\n \n subgraph \"Memory Integration\"\n AgentSession_memory[\"AgentSession._create_memory()\"]\n setup_memory[\"create_memory()<br/>(setup.py)\"]\n end\n \n Memory_init --> runtime_info\n Memory_init --> repo_info\n Memory_init --> microagents\n Memory_init --> conversation_instructions\n \n runtime_info --> Runtime_memory\n repo_info --> Repository\n microagents --> Microagents\n Memory_init --> EventStream_memory\n runtime_info --> UserSecrets\n \n AgentSession_memory --> Memory_init\n setup_memory --> Memory_init\n \n style Memory_init fill:#ffeeee\n style runtime_info fill:#eeffee\n style microagents fill:#eeeeff\n```\n\nSources: [openhands/memory/memory.py](), [openhands/server/session/agent_session.py:448-481](), [openhands/core/setup.py:157-199]()"
},
"Multi-Agent Coordination": {
"Delegation Architecture": "```\ngraph TD\n subgraph \"Parent Agent\"\n ParentController[\"AgentController<br/>parent: None<br/>delegate: AgentController\"]\n ParentAgent[\"Agent<br/>(Primary task agent)\"]\n end\n \n subgraph \"Delegation Process\"\n AgentDelegateAction[\"AgentDelegateAction<br/>agent: str<br/>inputs: dict\"]\n start_delegate[\"start_delegate()<br/>(agent_controller.py)\"]\n create_delegate_controller[\"Create Delegate Controller<br/>is_delegate=True\"]\n delegate_state[\"State<br/>delegate_level++<br/>shared metrics\"]\n end\n \n subgraph \"Delegate Agent\"\n DelegateController[\"AgentController<br/>parent: AgentController<br/>delegate: None\"]\n DelegateAgent[\"Agent<br/>(Specialized agent)\"]\n end\n \n subgraph \"Completion Process\"\n delegate_finish[\"AgentFinishAction<br/>AgentRejectAction<br/>ERROR state\"]\n end_delegate[\"end_delegate()<br/>(agent_controller.py)\"]\n AgentDelegateObservation[\"AgentDelegateObservation<br/>outputs: dict<br/>content: str\"]\n end\n \n ParentController --> ParentAgent\n ParentAgent --> AgentDelegateAction\n AgentDelegateAction --> start_delegate\n start_delegate --> create_delegate_controller\n create_delegate_controller --> delegate_state\n \n delegate_state --> DelegateController\n DelegateController --> DelegateAgent\n \n DelegateController --> delegate_finish\n delegate_finish --> end_delegate\n end_delegate --> AgentDelegateObservation\n AgentDelegateObservation --> ParentController\n \n style start_delegate fill:#ffeeee\n style end_delegate fill:#eeffee\n style delegate_state fill:#eeeeff\n```\n\nSources: [openhands/controller/agent_controller.py:693-753](), [openhands/controller/agent_controller.py:754-820](), [openhands/events/action/agent.py](), [openhands/events/observation/agent.py]()",
"Delegation State Management": "The delegation system maintains shared state across parent and child agents:\n\n['**Iteration Counter**: Shared across all agents to enforce global limits', '**Budget Tracking**: Global budget accumulation across delegation chain ', '**Metrics Collection**: Consolidated metrics from all agents', '**Event Stream**: Single event stream shared between parent and delegates', '**State Isolation**: Each agent maintains independent conversation state']\n\nSources: [openhands/controller/agent_controller.py:717-752](), [openhands/controller/state/state.py]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": [
{
"title": "Agent Controller & Orchestration",
"description": null,
"content": {
"Core Architecture": "The orchestration system is built around several key components that work together to manage agent execution:\n\n```\ngraph TB\n subgraph \"Session Layer\"\n WS[\"WebSession<br/>Client Connection\"]\n AS[\"AgentSession<br/>Agent Runtime Coordination\"]\n end\n \n subgraph \"Controller Layer\"\n AC[\"AgentController<br/>Central Orchestration Engine\"]\n ST[\"StateTracker<br/>State Management\"]\n SD[\"StuckDetector<br/>Loop Detection\"]\n end\n \n subgraph \"Agent Layer\" \n AGENT[\"Agent<br/>LLM-powered Decision Maker\"]\n DELEGATE[\"Delegate Agent<br/>Subtask Handler\"]\n end\n \n subgraph \"Event & Communication\"\n ES[\"EventStream<br/>Message Bus\"]\n EM[\"ReplayManager<br/>Trajectory Replay\"]\n end\n \n subgraph \"External Systems\"\n RT[\"Runtime<br/>Execution Environment\"]\n LLM[\"LLMRegistry<br/>Model Access\"]\n MEM[\"Memory<br/>Context Management\"]\n end\n \n WS --> AS\n AS --> AC\n AC --> ST\n AC --> SD\n AC --> AGENT\n AC --> DELEGATE\n AC --> ES\n AC --> EM\n \n AGENT --> LLM\n AC --> RT\n AC --> MEM\n \n ES --> RT\n ES --> WS\n```\n\n**Agent Controller Orchestration Flow**\n\nSources: [openhands/controller/agent_controller.py:100-200](), [openhands/server/session/agent_session.py:42-90](), [openhands/server/session/session.py:40-112]()\n\nThe `AgentController` class serves as the central orchestration engine, managing the complete lifecycle of agent execution. It coordinates between the agent's decision-making process, the runtime environment, and the user interface through an event-driven architecture.",
"Agent Controller Lifecycle": {
"State Management Implementation": "The `StateTracker` and controller work together to manage agent state transitions:\n\n| State | Description | Triggers | Next States |\n|-------|-------------|----------|-------------|\n| `LOADING` | Agent initializing | Session start | `RUNNING`, `ERROR` |\n| `RUNNING` | Agent actively processing | User message, observation | `AWAITING_USER_INPUT`, `STOPPED`, `ERROR`, `FINISHED` |\n| `AWAITING_USER_INPUT` | Waiting for user response | Agent requests input | `RUNNING` |\n| `AWAITING_USER_CONFIRMATION` | Security confirmation needed | High-risk action detected | `USER_CONFIRMED`, `USER_REJECTED` |\n| `STOPPED` | Agent halted by user | Stop button pressed | `RUNNING` |\n| `ERROR` | Error state | Exception occurred | `RUNNING` |\n| `FINISHED` | Task completed successfully | `AgentFinishAction` | Terminal |\n| `REJECTED` | Task rejected by agent | `AgentRejectAction` | Terminal |\n\nSources: [openhands/controller/agent_controller.py:631-683](), [openhands/controller/state/state_tracker.py]()"
},
"Event Orchestration": {
"Event Processing Logic": "The controller implements sophisticated event processing logic in the `should_step()` method:\n\n```\n# Key decision logic for when agent should take a step\ndef should_step(self, event: Event) -> bool:\n if self.delegate is not None:\n return False # Delegate is active\n \n if isinstance(event, MessageAction) and event.source == EventSource.USER:\n return True # User message triggers step\n \n if isinstance(event, Observation) and not isinstance(event, NullObservation):\n return True # Environment feedback triggers step\n```\n\nSources: [openhands/controller/agent_controller.py:392-431]()"
},
"Agent Delegation System": {
"Delegation Implementation Details": "The delegation system maintains separate execution contexts while sharing global resources:\n\n| Component | Parent | Delegate | Notes |\n|-----------|---------|----------|-------|\n| `event_stream` | Subscriber | Non-subscriber | Delegate doesn't directly subscribe |\n| `metrics` | Shared reference | Shared reference | Global accumulation |\n| `iteration_flag` | Parent counter | Delegate counter | Merged on completion |\n| `state` | Parent state | Isolated state | Separate delegate_level |\n| `sid` | Original | `{parent_sid}-delegate` | Unique identifier |\n\nSources: [openhands/controller/agent_controller.py:717-752]()"
},
"Session Management Integration": {
"Session Lifecycle Coordination": "The session management system coordinates the complete lifecycle from client connection to resource cleanup:\n\n['**Session Creation**: `WebSession` created on client connection with unique `sid`', '**Agent Initialization**: `AgentSession.start()` creates controller, runtime, memory', '**Event Processing**: Events flow through `EventStream` to `AgentController`', '**Resource Management**: Runtime containers, LLM connections managed per session', '**Session Cleanup**: `close()` methods ensure proper resource deallocation']\n\nSources: [openhands/server/session/agent_session.py:90-223](), [openhands/server/session/session.py:119-130]()"
},
"Integration Points": {
"Runtime Integration": [
"**Security Analysis**: Integration with `SecurityAnalyzer` for action risk assessment",
"**Action Execution**: Direct communication with runtime for command execution",
"**Status Callbacks**: Runtime status updates propagated through controller"
],
"LLM Integration": [
"**Registry Access**: Controller accesses LLM services through `LLMRegistry`",
"**Error Handling**: Comprehensive LLM error handling with state transitions",
"**Budget Management**: LLM usage tracking and budget enforcement"
],
"Memory Integration": [
"**Context Management**: Memory system provides conversation context to agents",
"**Microagent Loading**: Integration with workspace-specific microagents",
"**Repository Information**: Git repository context and branch management"
],
"Error Handling and Recovery": "The controller implements comprehensive error handling with automatic recovery mechanisms:\n\n```\ngraph TD\n subgraph \"Error Detection\"\n EXCEPTION[\"Exception Caught\"]\n ERROR_TYPE{\"Error Type Analysis\"}\n end\n \n subgraph \"Error Classification\"\n AUTH_ERR[\"AuthenticationError<br/>ERROR_LLM_AUTHENTICATION\"]\n RATE_ERR[\"RateLimitError<br/>RATE_LIMITED State\"]\n BUDGET_ERR[\"ExceededBudget<br/>ERROR_LLM_OUT_OF_CREDITS\"]\n CONTENT_ERR[\"ContentPolicyViolationError<br/>ERROR_LLM_CONTENT_POLICY\"]\n STUCK_ERR[\"AgentStuckInLoopError<br/>Loop Detection\"]\n end\n \n subgraph \"Error Response\"\n STATE_UPDATE[\"set_agent_state_to(AgentState.ERROR)\"]\n STATUS_CALLBACK[\"status_callback('error', ...)\"]\n ERROR_STORAGE[\"state.last_error = error_message\"]\n USER_NOTIFICATION[\"Error message to user\"]\n end\n \n EXCEPTION --> ERROR_TYPE\n ERROR_TYPE --> AUTH_ERR\n ERROR_TYPE --> RATE_ERR\n ERROR_TYPE --> BUDGET_ERR\n ERROR_TYPE --> CONTENT_ERR\n ERROR_TYPE --> STUCK_ERR\n \n AUTH_ERR --> STATE_UPDATE\n RATE_ERR --> STATE_UPDATE\n BUDGET_ERR --> STATE_UPDATE\n CONTENT_ERR --> STATE_UPDATE\n STUCK_ERR --> STATE_UPDATE\n \n STATE_UPDATE --> STATUS_CALLBACK\n STATE_UPDATE --> ERROR_STORAGE\n STATE_UPDATE --> USER_NOTIFICATION\n```\n\n**Error Handling and Recovery System**\n\nSources: [openhands/controller/agent_controller.py:302-390](), [openhands/controller/agent_controller.py:849-860](), [openhands/controller/stuck.py]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
},
{
"title": "Memory & Prompt Management",
"description": null,
"content": {
"System Overview": {
"Memory & Prompt System Architecture": "```\ngraph TB\n subgraph \"Event Processing\"\n ES[EventStream] \n RA[RecallAction]\n Events[Event History]\n end\n \n subgraph \"Memory System\"\n Memory[Memory]\n RM[repo_microagents]\n KM[knowledge_microagents]\n RO[RecallObservation]\n end\n \n subgraph \"Conversation Processing\"\n CM[ConversationMemory]\n Messages[Message List]\n ToolCalls[Tool Call Processing]\n end\n \n subgraph \"Prompt Generation\"\n PM[PromptManager]\n ST[system_template]\n UT[user_template]\n AIT[additional_info_template]\n MIT[microagent_info_template]\n end\n \n subgraph \"Templates\"\n SysPrompt[system_prompt.j2]\n UserPrompt[user_prompt.j2]\n AdditionalInfo[additional_info.j2]\n MicroagentInfo[microagent_info.j2]\n end\n \n ES --> Memory\n RA --> Memory\n Memory --> RM\n Memory --> KM\n Memory --> RO\n \n Events --> CM\n RO --> CM\n CM --> Messages\n CM --> ToolCalls\n \n CM --> PM\n PM --> ST\n PM --> UT\n PM --> AIT\n PM --> MIT\n \n ST --> SysPrompt\n UT --> UserPrompt\n AIT --> AdditionalInfo\n MIT --> MicroagentInfo\n```\n\nSources: [openhands/memory/memory.py:41-388](), [openhands/memory/conversation_memory.py:55-861](), [openhands/utils/prompt.py:43-152]()"
},
"Core Components": {
"Memory Class": "The `Memory` class serves as the central hub for knowledge retrieval and microagent management. It subscribes to the event stream and processes `RecallAction` events to provide contextual information.\n\n| Component | Purpose | Location |\n|-----------|---------|----------|\n| `repo_microagents` | Repository-specific guidance and instructions | [openhands/memory/memory.py:71]() |\n| `knowledge_microagents` | Keyword-triggered knowledge base | [openhands/memory/memory.py:72]() |\n| `repository_info` | Git repository context (name, directory, branch) | [openhands/memory/memory.py:75]() |\n| `runtime_info` | Environment details (hosts, ports, date) | [openhands/memory/memory.py:76]() |\n| `conversation_instructions` | Task-specific guidance | [openhands/memory/memory.py:77]() |",
"ConversationMemory Class": "The `ConversationMemory` class processes event history into structured `Message` objects that LLMs can understand. It handles both traditional text-based interactions and function calling modes.\n\nKey methods:\n\n['`process_events()` - Main entry point for converting events to messages', '`_process_action()` - Converts Action events to assistant messages', '`_process_observation()` - Converts Observation events to user/tool messages', '`apply_prompt_caching()` - Optimizes prompt caching for Anthropic models']",
"PromptManager Class": "The `PromptManager` uses Jinja2 templates to generate prompts with dynamic content injection. It loads templates from the agent's prompt directory and provides methods for building different prompt components.\n\nSources: [openhands/memory/memory.py:41-88](), [openhands/memory/conversation_memory.py:55-74](), [openhands/utils/prompt.py:43-70]()"
},
"Event Processing Flow": {
"Event to Message Conversion Flow": "```\ngraph TD\n subgraph \"Input Events\"\n Actions[Action Events]\n Observations[Observation Events]\n RecallActions[RecallAction Events]\n end\n \n subgraph \"Processing Pipeline\"\n EnsureSystem[_ensure_system_message]\n EnsureUser[_ensure_initial_user_message]\n ProcessLoop[Event Processing Loop]\n ProcessAction[_process_action]\n ProcessObs[_process_observation]\n end\n \n subgraph \"Function Calling Mode\"\n PendingToolCalls[pending_tool_call_action_messages]\n ToolCallMap[tool_call_id_to_message]\n FilterUnmatched[_filter_unmatched_tool_calls]\n end\n \n subgraph \"Output\"\n MessageList[Message List]\n ApplyFormatting[_apply_user_message_formatting]\n FinalMessages[Final LLM Messages]\n end\n \n Actions --> ProcessLoop\n Observations --> ProcessLoop\n RecallActions --> Memory\n \n ProcessLoop --> EnsureSystem\n ProcessLoop --> EnsureUser\n ProcessLoop --> ProcessAction\n ProcessLoop --> ProcessObs\n \n ProcessAction --> PendingToolCalls\n ProcessObs --> ToolCallMap\n PendingToolCalls --> FilterUnmatched\n ToolCallMap --> FilterUnmatched\n \n FilterUnmatched --> MessageList\n MessageList --> ApplyFormatting\n ApplyFormatting --> FinalMessages\n```\n\nThe processing handles different event types with specific logic:\n\n| Event Type | Processing Method | Output |\n|------------|-------------------|---------|\n| `MessageAction` | `_process_action()` | User/assistant messages with text/image content |\n| `CmdRunAction` | `_process_action()` | Tool calls (function mode) or user messages |\n| `CmdOutputObservation` | `_process_observation()` | Tool responses (function mode) or user messages |\n| `RecallAction` | Memory system | `RecallObservation` with context/knowledge |\n\nSources: [openhands/memory/conversation_memory.py:74-164](), [openhands/memory/conversation_memory.py:183-342](), [openhands/memory/conversation_memory.py:344-681]()"
},
"Microagent System": {
"Microagent Types and Loading": "| Type | Purpose | Storage | Loading Method |\n|------|---------|---------|----------------|\n| `KnowledgeMicroagent` | Keyword-triggered knowledge base | `knowledge_microagents` dict | `_load_global_microagents()` |\n| `RepoMicroagent` | Repository-specific instructions | `repo_microagents` dict | `load_user_workspace_microagents()` |\n\nMicroagents are loaded from multiple sources:\n\n['Global microagents: `OpenHands/microagents/` directory', 'User microagents: `~/.openhands/microagents/` directory ', 'Workspace microagents: Loaded dynamically from cloned repositories']",
"Knowledge Retrieval Process": "The `_find_microagent_knowledge()` method searches for matching microagents:\n\n```\ngraph LR\n Query[User Query] --> SearchTriggers[Search Trigger Keywords]\n SearchTriggers --> MatchFound{Match Found?}\n MatchFound -->|Yes| CreateKnowledge[Create MicroagentKnowledge]\n MatchFound -->|No| Continue[Continue Search]\n CreateKnowledge --> KnowledgeList[Knowledge List]\n Continue --> KnowledgeList\n KnowledgeList --> RecallObs[RecallObservation]\n```\n\nSources: [openhands/memory/memory.py:225-252](), [openhands/memory/memory.py:254-278](), [openhands/memory/memory.py:280-301]()"
},
"Prompt Template System": {
"Template Structure": "| Template | Purpose | Context Variables |\n|----------|---------|-------------------|\n| `system_prompt.j2` | Base system instructions | Agent config, CLI mode |\n| `user_prompt.j2` | Example user message | Task demonstrations |\n| `additional_info.j2` | Workspace context | Repository, runtime, conversation info |\n| `microagent_info.j2` | Triggered microagent knowledge | Microagent knowledge list |",
"Context Building Process": "The `PromptManager` builds context through specialized methods:\n\n['`build_workspace_context()` - Combines repository, runtime, and conversation information', '`build_microagent_info()` - Formats triggered microagent knowledge', '`get_system_message()` - Generates complete system prompt', '`add_turns_left_reminder()` - Adds turn count reminders for finite conversations']",
"Workspace Context Template": "The `additional_info.j2` template structures workspace information:\n\n```\n{% if repository_info %}\n<REPOSITORY_INFO>\nAt the user's request, repository {{ repository_info.repo_name }} has been cloned to {{ repository_info.repo_directory }}\n{% if repository_info.branch_name %}\nThe repository has been checked out to branch \"{{ repository_info.branch_name }}\"\n{% endif %}\n</REPOSITORY_INFO>\n{% endif %}\n```\n\nSources: [openhands/utils/prompt.py:89-94](), [openhands/utils/prompt.py:107-134](), [openhands/agenthub/codeact_agent/prompts/additional_info.j2:1-54]()"
},
"Tool Calling & Function Calling Mode": {
"Function Calling Pipeline": "```\ngraph TD\n subgraph \"Action Processing\"\n AgentAction[Agent Action with tool_call_metadata]\n ExtractResponse[Extract ModelResponse]\n StorePending[Store in pending_tool_call_action_messages]\n end\n \n subgraph \"Observation Processing\" \n ToolObs[Tool Observation with tool_call_metadata]\n CreateToolMsg[Create Tool Message]\n StoreToolMap[Store in tool_call_id_to_message]\n end\n \n subgraph \"Message Assembly\"\n CheckComplete[Check All Tool Calls Complete]\n AssembleMessages[Assemble Assistant + Tool Messages]\n FilterUnmatched[Filter Unmatched Tool Calls]\n end\n \n AgentAction --> ExtractResponse\n ExtractResponse --> StorePending\n \n ToolObs --> CreateToolMsg\n CreateToolMsg --> StoreToolMap\n \n StorePending --> CheckComplete\n StoreToolMap --> CheckComplete\n CheckComplete --> AssembleMessages\n AssembleMessages --> FilterUnmatched\n```\n\nThe system maintains two key mappings during function calling:\n\n['`pending_tool_call_action_messages` - Maps response IDs to assistant messages with tool calls', '`tool_call_id_to_message` - Maps tool call IDs to their corresponding tool response messages']",
"Tool Call Validation": "The `_filter_unmatched_tool_calls()` method ensures message consistency:\n\n['Removes tool messages without matching assistant tool calls', 'Removes assistant tool calls without matching tool responses', 'Preserves message ordering and relationships']\n\nSources: [openhands/memory/conversation_memory.py:105-156](), [openhands/memory/conversation_memory.py:669-680](), [openhands/memory/conversation_memory.py:746-799]()"
},
"Context Management": {
"Context Information Types": "| Context Type | Source | Content |\n|--------------|--------|---------|\n| Repository Context | Git operations | Repo name, directory, branch, instructions |\n| Runtime Context | Sandbox environment | Available hosts, ports, working directory, date |\n| Conversation Context | User/system instructions | Task-specific guidance and constraints |\n| Microagent Context | Knowledge base | Triggered expertise and recommendations |",
"Context Injection Process": "Context is injected into conversations through `RecallObservation` events:\n\n['**Workspace Context Recall** - Triggered on first user message', '**Knowledge Recall** - Triggered by keyword matching in user/agent messages ', '**Template Rendering** - Context formatted through Jinja2 templates', '**Message Integration** - Context added as user messages in conversation']",
"Vision and Image Handling": "The system supports multimodal interactions with special handling for images:\n\n['`ImageContent` objects for image URLs', 'Vision-aware content filtering and validation', 'Browser screenshot and Set-of-Marks integration', 'Base64 image cleanup in IPython outputs']\n\nSources: [openhands/memory/memory.py:139-224](), [openhands/memory/conversation_memory.py:527-680](), [openhands/events/observation/agent.py:62-139]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
},
{
"title": "Function Calling & Actions",
"description": null,
"content": {
"Action-Observation Cycle Overview": "OpenHands operates on a fundamental action-observation cycle where agents receive LLM responses containing tool calls, convert them to typed Action objects, execute them in sandboxed environments, and process the resulting Observation objects.\n\n```\ngraph TB\n LLM[\"LLM Response\"] --> FC[\"Function Calling Parser\"]\n FC --> Action[\"Action Objects\"]\n Action --> Executor[\"Action Execution\"]\n Executor --> Obs[\"Observation Objects\"]\n Obs --> Memory[\"Agent Memory\"]\n Memory --> LLM\n \n subgraph \"Action Types\"\n CmdAction[\"CmdRunAction\"]\n FileAction[\"FileReadAction / FileEditAction\"]\n IPythonAction[\"IPythonRunCellAction\"]\n BrowserAction[\"BrowseInteractiveAction\"]\n ThinkAction[\"AgentThinkAction\"]\n FinishAction[\"AgentFinishAction\"]\n end\n \n Action --> CmdAction\n Action --> FileAction\n Action --> IPythonAction\n Action --> BrowserAction\n Action --> ThinkAction\n Action --> FinishAction\n```\n\nSources: [openhands/agenthub/codeact_agent/function_calling.py:73-338](), [frontend/src/services/actions.ts:17-43](), [frontend/src/services/observations.ts:9-86]()",
"Function Calling Mechanism": {
"LLM Response Processing": "```\ngraph TD\n ModelResponse[\"ModelResponse from LLM\"] --> Choice[\"Extract Choice[0]\"]\n Choice --> Message[\"assistant_msg\"]\n Message --> ToolCalls{\"Has tool_calls?\"}\n \n ToolCalls -->|Yes| ProcessTools[\"Process Each Tool Call\"]\n ToolCalls -->|No| MessageAction[\"Create MessageAction\"]\n \n ProcessTools --> ParseArgs[\"JSON Parse Arguments\"]\n ParseArgs --> ValidateTool[\"Validate Tool Name\"]\n ValidateTool --> CreateAction[\"Create Typed Action\"]\n CreateAction --> AddMetadata[\"Add ToolCallMetadata\"]\n AddMetadata --> ActionList[\"Action Objects List\"]\n \n MessageAction --> ActionList\n ActionList --> Return[\"Return List[Action]\"]\n```\n\nThe function calling parser handles multiple tool calls in a single response and extracts any accompanying text content as \"thought\" information.\n\nSources: [openhands/agenthub/codeact_agent/function_calling.py:73-90](), [openhands/agenthub/codeact_agent/function_calling.py:313-321]()",
"Tool Name Mapping": "Each LLM tool call is mapped to a specific Action class based on the function name:\n\n| Tool Function Name | Action Class | Purpose |\n|-------------------|--------------|---------|\n| `str_replace_editor` | `FileEditAction` / `FileReadAction` | File editing operations |\n| `bash` | `CmdRunAction` | Shell command execution |\n| `ipython` | `IPythonRunCellAction` | Python code execution |\n| `agent_think` | `AgentThinkAction` | Agent reasoning |\n| `finish` | `AgentFinishAction` | Task completion |\n| `browser` | `BrowseInteractiveAction` | Browser interaction |\n\nSources: [openhands/agenthub/codeact_agent/function_calling.py:105-310]()"
},
"Action Types and Implementations": {
"Command Execution Actions": {
"CmdRunAction": "Executes shell commands in the sandboxed environment with support for input pipes, timeouts, and security risk assessment.\n\n```\ngraph LR\n CmdRunAction --> Runtime[\"Runtime Environment\"]\n Runtime --> Shell[\"Bash Process\"]\n Shell --> PS1[\"PS1 Metadata Capture\"]\n PS1 --> CmdOutputObservation\n \n CmdRunAction -.-> SecurityRisk[\"Security Risk Assessment\"]\n CmdRunAction -.-> Timeout[\"Hard Timeout\"]\n```\n\nKey attributes:\n\n['`command`: The shell command to execute', '`is_input`: Whether this is input to a running process', '`security_risk`: Risk level assessment', '`confirmation_state`: User confirmation status']\n\nSources: [openhands/events/action/commands.py:12-40](), [openhands/agenthub/codeact_agent/function_calling.py:105-123]()",
"IPythonRunCellAction": "Executes Python code in a Jupyter kernel environment with support for rich output including images.\n\nSources: [openhands/events/action/commands.py:42-65](), [openhands/agenthub/codeact_agent/function_calling.py:127-133]()"
},
"File Operations Actions": {
"File Editor Tool Integration": "The `str_replace_editor` tool provides unified file operations with command-based dispatch:\n\n```\ngraph TD\n StrReplaceEditor[\"str_replace_editor Tool Call\"] --> Command{\"command arg\"}\n Command -->|view| FileReadAction\n Command -->|str_replace| FileEditAction[\"FileEditAction with str_replace\"]\n Command -->|create| FileEditAction2[\"FileEditAction with create\"]\n \n FileReadAction --> ViewRange[\"Optional view_range\"]\n FileEditAction --> OldStr[\"old_str / new_str\"]\n FileEditAction2 --> FileText[\"file_text content\"]\n \n subgraph \"Implementation Sources\"\n OHACI[\"OH_ACI (OpenHands ACI)\"]\n LLMBased[\"LLM_BASED_EDIT (Legacy)\"]\n end\n \n FileReadAction --> OHACI\n FileEditAction --> OHACI\n FileEditAction2 --> OHACI\n```\n\nSources: [openhands/agenthub/codeact_agent/function_calling.py:173-229](), [openhands/events/action/files.py]()"
},
"Agent Control Actions": {
"AgentThinkAction": "Records agent reasoning and internal thoughts without external side effects.",
"AgentFinishAction ": "Signals task completion with final thoughts and optional output data.",
"AgentDelegateAction": "Delegates subtasks to specialized agents (e.g., BrowsingAgent).\n\nSources: [openhands/events/action/agent.py:22-86](), [openhands/agenthub/codeact_agent/function_calling.py:138-150]()"
}
},
"Security and Validation": {
"Function Call Validation": "All tool calls undergo strict validation before conversion to actions:\n\n```\ngraph TD\n ToolCall[\"Tool Call\"] --> ParseJSON[\"Parse JSON Arguments\"]\n ParseJSON --> ValidateName[\"Validate Function Name\"]\n ValidateName --> RequiredArgs[\"Check Required Arguments\"]\n RequiredArgs --> SecurityRisk[\"Assess Security Risk\"]\n SecurityRisk --> CreateAction[\"Create Action Object\"]\n \n ParseJSON -->|JSON Error| FunctionCallValidationError\n ValidateName -->|Unknown Tool| FunctionCallNotExistsError\n RequiredArgs -->|Missing Args| FunctionCallValidationError\n```",
"Security Risk Assessment": "Actions can be tagged with security risk levels that affect execution:\n\n['`UNKNOWN`: Default risk level', '`LOW`: Safe operations', '`MEDIUM`: Potentially risky operations ', '`HIGH`: Dangerous operations requiring confirmation']\n\nThe `set_security_risk` function processes risk annotations from tool calls.\n\nSources: [openhands/agenthub/codeact_agent/function_calling.py:59-71](), [openhands/agenthub/codeact_agent/tools/security_utils.py](), [openhands/events/action/action.py]()"
},
"Observation Processing": {
"Command Output Observations": "Command execution results are captured in `CmdOutputObservation` objects with rich metadata:\n\n```\ngraph LR\n CmdExecution[\"Command Execution\"] --> PS1Capture[\"PS1 Metadata Capture\"]\n PS1Capture --> CmdOutputMetadata[\"CmdOutputMetadata\"]\n CmdOutputMetadata --> Fields[\"exit_code, pid, working_dir, py_interpreter_path\"]\n \n CmdExecution --> Content[\"Command Output Content\"]\n Content --> Truncation[\"Content Truncation (30KB limit)\"]\n \n CmdOutputMetadata --> CmdOutputObservation\n Truncation --> CmdOutputObservation\n```\n\nThe PS1 prompt injection captures structured metadata about command execution context.\n\nSources: [openhands/events/observation/commands.py:26-95](), [openhands/events/observation/commands.py:140-166]()",
"IPython Observations": "Python code execution produces `IPythonRunCellObservation` objects that can include image outputs for rich display.\n\nSources: [openhands/events/observation/commands.py:208-233]()"
},
"Frontend Integration": {
"Action Handling": "The frontend processes incoming actions through the `handleActionMessage` function:\n\n```\ngraph TD\n ActionMessage[\"ActionMessage from Backend\"] --> Hidden{\"args.hidden?\"}\n Hidden -->|Yes| Skip[\"Skip Processing\"]\n Hidden -->|No| Metrics[\"Update LLM Metrics\"]\n \n Metrics --> ActionType{\"Action Type\"}\n ActionType -->|RUN| CommandSlice[\"Append to Command Slice\"]\n ActionType -->|RUN_IPYTHON| JupyterSlice[\"Append to Jupyter Slice\"]\n ActionType -->|Security Risk| SecurityAnalyzer[\"Security Analyzer Slice\"]\n \n CommandSlice --> Store[\"Redux Store\"]\n JupyterSlice --> Store\n SecurityAnalyzer --> Store\n```\n\nSources: [frontend/src/services/actions.ts:17-43]()",
"Observation Handling": "Observations are processed to update various UI states:\n\n['`RUN` observations update command terminal output', '`RUN_IPYTHON` observations update Jupyter notebook display', '`BROWSE_INTERACTIVE` observations update browser screenshots and URLs', '`AGENT_STATE_CHANGED` observations update agent status']\n\nSources: [frontend/src/services/observations.ts:9-86](), [frontend/src/types/core/observations.ts:13-179]()",
"Type Safety": "The frontend maintains strict TypeScript types for all actions and observations, ensuring type safety across the action-observation cycle.\n\nSources: [frontend/src/types/core/actions.ts:1-198](), [frontend/src/types/core/observations.ts:164-179]()"
},
"Tool Call Metadata": "Every action created from a tool call includes `ToolCallMetadata` that tracks:\n\n['`tool_call_id`: Unique identifier for the tool call', '`function_name`: Name of the called function', '`model_response`: Reference to the original LLM response', '`total_calls_in_response`: Number of concurrent tool calls']\n\nThis metadata enables correlation between actions and LLM token usage for cost tracking and debugging.\n\nSources: [openhands/agenthub/codeact_agent/function_calling.py:315-321](), [openhands/events/tool.py]()"
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
}
]
},
{
"title": "LLM Integration",
"description": null,
"content": {
"Purpose and Scope": "This document covers OpenHands' Language Model (LLM) integration system, which provides a unified interface for interacting with multiple LLM providers through a centralized abstraction layer. The system handles model configuration, request processing, response formatting, metrics tracking, and provider-specific optimizations.\n\nFor information about how agents use LLMs for decision-making and action generation, see [Agent System](#3). For details about the runtime execution environment, see [Runtime & Execution Environment](#5).",
"Architecture Overview": "OpenHands implements a layered LLM integration architecture that abstracts provider-specific details while maintaining flexibility for advanced features.\n\n```\ngraph TD\n subgraph \"Application Layer\"\n Agent[\"CodeActAgent\"]\n ConvMem[\"ConversationMemory\"]\n PromptMgr[\"PromptManager\"]\n end\n \n subgraph \"LLM Abstraction Layer\"\n LLMReg[\"LLMRegistry\"]\n LLMClass[\"LLM\"]\n AsyncLLM[\"AsyncLLM\"] \n StreamLLM[\"StreamingLLM\"]\n end\n \n subgraph \"Configuration Layer\"\n LLMConfig[\"LLMConfig\"]\n AgentConfig[\"AgentConfig\"]\n OpenHandsConfig[\"OpenHandsConfig\"]\n end\n \n subgraph \"Processing Layer\"\n Message[\"Message\"]\n Metrics[\"Metrics\"]\n DebugMixin[\"DebugMixin\"]\n RetryMixin[\"RetryMixin\"]\n end\n \n subgraph \"Provider Interface\"\n LiteLLM[\"LiteLLM\"]\n FnCallConverter[\"fn_call_converter\"]\n ModelFeatures[\"model_features\"]\n end\n \n subgraph \"External Providers\"\n OpenAI[\"OpenAI\"]\n Anthropic[\"Anthropic\"]\n Google[\"Google\"]\n Local[\"Local Models\"]\n end\n \n Agent --> LLMReg\n ConvMem --> Message\n PromptMgr --> Message\n \n LLMReg --> LLMClass\n LLMReg --> AsyncLLM\n LLMReg --> StreamLLM\n \n LLMClass --> LLMConfig\n LLMClass --> Metrics\n LLMClass --> DebugMixin\n LLMClass --> RetryMixin\n \n LLMConfig --> OpenHandsConfig\n AgentConfig --> LLMConfig\n \n Message --> LiteLLM\n LLMClass --> LiteLLM\n LLMClass --> FnCallConverter\n LLMClass --> ModelFeatures\n \n LiteLLM --> OpenAI\n LiteLLM --> Anthropic\n LiteLLM --> Google\n LiteLLM --> Local\n```\n\n**Sources:** [openhands/llm/llm.py:1-821](), [openhands/agenthub/codeact_agent/codeact_agent.py:1-300](), [openhands/core/config/llm_config.py:1-195]()",
"Configuration System": {
"LLMConfig Structure": "The `LLMConfig` class defines comprehensive LLM parameters:\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `model` | `str` | Model identifier (e.g., \"gpt-4o\", \"claude-sonnet-4\") |\n| `api_key` | `SecretStr` | Provider API key |\n| `base_url` | `str` | Custom API endpoint |\n| `temperature` | `float` | Sampling temperature (0.0-2.0) |\n| `max_output_tokens` | `int` | Maximum response tokens |\n| `num_retries` | `int` | Retry attempts for failed requests |\n| `caching_prompt` | `bool` | Enable prompt caching when supported |\n| `native_tool_calling` | `bool` | Use provider's native function calling |\n\n**Sources:** [openhands/core/config/llm_config.py:12-96]()",
"Configuration Loading Flow": "```\ngraph LR\n subgraph \"Configuration Sources\"\n EnvVars[\"Environment Variables\"]\n TOMLFile[\"config.toml\"]\n Defaults[\"Default Values\"]\n end\n \n subgraph \"Loading Process\"\n LoadToml[\"load_from_toml()\"]\n LoadEnv[\"load_from_env()\"] \n FromSection[\"LLMConfig.from_toml_section()\"]\n end\n \n subgraph \"Configuration Objects\"\n OpenHandsConfig[\"OpenHandsConfig\"]\n LLMConfigs[\"llms: dict[str, LLMConfig]\"]\n DefaultLLM[\"Default LLM Config\"]\n end\n \n TOMLFile --> LoadToml\n EnvVars --> LoadEnv\n Defaults --> OpenHandsConfig\n \n LoadToml --> FromSection\n LoadEnv --> LLMConfigs\n FromSection --> LLMConfigs\n \n LLMConfigs --> OpenHandsConfig\n DefaultLLM --> OpenHandsConfig\n```\n\n**Sources:** [openhands/core/config/utils.py:138-212](), [openhands/core/config/llm_config.py:100-160]()"
},
"LLM Class Hierarchy": {
"Core LLM Class": "The base `LLM` class handles synchronous requests with comprehensive error handling and metrics:\n\n```\ngraph TD\n subgraph \"LLM Class Components\"\n LLMInit[\"__init__()\"]\n Completion[\"completion()\"]\n PostProcess[\"_post_completion()\"]\n ModelInfo[\"init_model_info()\"]\n end\n \n subgraph \"Mixins\"\n RetryMixin[\"RetryMixin\"]\n DebugMixin[\"DebugMixin\"]\n end\n \n subgraph \"Configuration\"\n LLMConfig[\"LLMConfig\"]\n Metrics[\"Metrics\"]\n ServiceId[\"service_id\"]\n end\n \n subgraph \"LiteLLM Integration\"\n PartialFunc[\"partial(litellm_completion)\"]\n Wrapper[\"retry_decorator wrapper\"]\n Features[\"get_features()\"]\n end\n \n RetryMixin --> LLMInit\n DebugMixin --> LLMInit\n LLMConfig --> LLMInit\n Metrics --> LLMInit\n ServiceId --> LLMInit\n \n LLMInit --> ModelInfo\n LLMInit --> PartialFunc\n PartialFunc --> Wrapper\n Wrapper --> Completion\n \n Completion --> PostProcess\n PostProcess --> Metrics\n \n Features --> ModelInfo\n```\n\n**Sources:** [openhands/llm/llm.py:54-821](), [openhands/llm/retry_mixin.py:15-101](), [openhands/llm/debug_mixin.py:13-74]()",
"Async and Streaming Variants": [
"**AsyncLLM**: Extends `LLM` for non-blocking operations with cancellation support",
"**StreamingLLM**: Extends `AsyncLLM` for real-time token streaming"
]
},
"Message Processing Pipeline": {
"Message Structure and Serialization": "```\ngraph TD\n subgraph \"Message Components\"\n MessageClass[\"Message\"]\n TextContent[\"TextContent\"]\n ImageContent[\"ImageContent\"]\n ToolCalls[\"tool_calls\"]\n end\n \n subgraph \"Serialization Logic\"\n SerializeModel[\"serialize_model()\"]\n StringSerializer[\"_string_serializer()\"]\n ListSerializer[\"_list_serializer()\"]\n AddToolKeys[\"_add_tool_call_keys()\"]\n end\n \n subgraph \"Provider Features\"\n VisionEnabled[\"vision_enabled\"]\n CacheEnabled[\"cache_enabled\"] \n FunctionCalling[\"function_calling_enabled\"]\n ForceString[\"force_string_serializer\"]\n end\n \n subgraph \"Output Formats\"\n StringFormat[\"String Format\"]\n ListFormat[\"List Format\"]\n end\n \n MessageClass --> TextContent\n MessageClass --> ImageContent\n MessageClass --> ToolCalls\n \n MessageClass --> SerializeModel\n SerializeModel --> StringSerializer\n SerializeModel --> ListSerializer\n \n VisionEnabled --> ListSerializer\n CacheEnabled --> ListSerializer\n FunctionCalling --> ListSerializer\n ForceString --> StringSerializer\n \n StringSerializer --> AddToolKeys\n ListSerializer --> AddToolKeys\n \n AddToolKeys --> StringFormat\n AddToolKeys --> ListFormat\n```\n\n**Sources:** [openhands/core/message.py:53-159]()",
"Conversation Memory Integration": "The `ConversationMemory` class processes events into properly formatted messages:\n\n**Sources:** [openhands/agenthub/codeact_agent/codeact_agent.py:282-293]()"
},
"Multi-Provider Support": {
"Provider-Specific Handling": "```\ngraph TD\n subgraph \"Provider Detection\"\n ModelName[\"config.model\"]\n Features[\"get_features()\"]\n ProviderCheck[\"Provider String Matching\"]\n end\n \n subgraph \"OpenAI Handling\"\n OpenAIModels[\"gpt-4*, o1-*, o3-*\"]\n ReasoningEffort[\"reasoning_effort\"]\n TemperatureDisable[\"temperature removal\"]\n end\n \n subgraph \"Anthropic Handling\" \n ClaudeModels[\"claude-*\"]\n CacheControl[\"cache_control\"]\n ThinkingDisabled[\"thinking: disabled\"]\n end\n \n subgraph \"Google Handling\"\n GeminiModels[\"gemini-*\"]\n ThinkingBudget[\"thinking.budget_tokens\"]\n SafetySettings[\"safety_settings\"]\n end\n \n subgraph \"Azure Handling\"\n AzureModels[\"azure/*\"]\n MaxTokens[\"max_tokens vs max_completion_tokens\"]\n APIVersion[\"api_version default\"]\n end\n \n ModelName --> ProviderCheck\n Features --> ProviderCheck\n \n ProviderCheck --> OpenAIModels\n ProviderCheck --> ClaudeModels\n ProviderCheck --> GeminiModels\n ProviderCheck --> AzureModels\n \n OpenAIModels --> ReasoningEffort\n OpenAIModels --> TemperatureDisable\n \n ClaudeModels --> CacheControl\n ClaudeModels --> ThinkingDisabled\n \n GeminiModels --> ThinkingBudget\n GeminiModels --> SafetySettings\n \n AzureModels --> MaxTokens\n AzureModels --> APIVersion\n```\n\n**Sources:** [openhands/llm/llm.py:125-193](), [openhands/core/config/llm_config.py:175-184]()"
},
"Advanced Features": {
"Function Calling Support": "OpenHands supports both native function calling and mock function calling through prompt engineering:\n\n| Feature | Native | Mock |\n|---------|--------|------|\n| Tool Schema | Sent as `tools` parameter | Embedded in prompt |\n| Response Format | Structured tool calls | Text with function tags |\n| Stop Words | Not used | Added to prevent overgeneration |\n| Conversion | Direct processing | `fn_call_converter` module |\n\n**Sources:** [openhands/llm/llm.py:226-293](), [openhands/llm/fn_call_converter.py:35-38]()",
"Prompt Caching": "When supported by the provider, OpenHands enables prompt caching to reduce costs:\n\n['**Anthropic**: Uses `cache_control: ephemeral` markers', '**OpenAI**: Automatic for supported models', '**Configuration**: Controlled by `caching_prompt` setting']\n\n**Sources:** [openhands/core/message.py:34-36](), [openhands/llm/llm.py:101-102]()",
"Vision Support": "Multi-modal models can process images alongside text:\n\n['**Detection**: Uses `litellm.supports_vision()` and model info', '**Content Format**: `ImageContent` with multiple image URLs', '**Provider Support**: Varies by model capabilities']\n\n**Sources:** [openhands/llm/llm.py:530-563]()"
},
"Metrics and Monitoring": {
"Metrics Collection Flow": "```\ngraph TD\n subgraph \"Metrics Components\"\n MetricsClass[\"Metrics\"]\n Cost[\"Cost\"]\n TokenUsage[\"TokenUsage\"]\n ResponseLatency[\"ResponseLatency\"]\n end\n \n subgraph \"Collection Points\"\n PostCompletion[\"_post_completion()\"]\n CompletionCost[\"_completion_cost()\"]\n AddTokenUsage[\"add_token_usage()\"]\n AddLatency[\"add_response_latency()\"]\n end\n \n subgraph \"Data Sources\"\n LiteLLMResponse[\"ModelResponse\"]\n UsageField[\"response.usage\"]\n HiddenParams[\"response._hidden_params\"]\n StartTime[\"time.time()\"]\n end\n \n subgraph \"Tracked Metrics\"\n AccumCost[\"accumulated_cost\"]\n PromptTokens[\"prompt_tokens\"]\n CompletionTokens[\"completion_tokens\"] \n CacheTokens[\"cache_read/write_tokens\"]\n LatencyTime[\"latency\"]\n end\n \n PostCompletion --> CompletionCost\n PostCompletion --> AddTokenUsage\n PostCompletion --> AddLatency\n \n LiteLLMResponse --> UsageField\n LiteLLMResponse --> HiddenParams\n StartTime --> AddLatency\n \n CompletionCost --> AccumCost\n AddTokenUsage --> PromptTokens\n AddTokenUsage --> CompletionTokens\n AddTokenUsage --> CacheTokens\n AddLatency --> LatencyTime\n \n MetricsClass --> Cost\n MetricsClass --> TokenUsage\n MetricsClass --> ResponseLatency\n```\n\n**Sources:** [openhands/llm/llm.py:583-666](), [openhands/llm/metrics.py:47-274]()"
},
"Error Handling and Retry Logic": {
"Retry Strategy": "The `RetryMixin` provides configurable exponential backoff with specific handling for different error types:\n\n| Exception Type | Retry Behavior | Special Handling |\n|---------------|----------------|------------------|\n| `RateLimitError` | Exponential backoff | Standard retry |\n| `APIConnectionError` | Exponential backoff | Standard retry |\n| `LLMNoResponseError` | Exponential backoff | Temperature increase to 1.0 |\n| `ServiceUnavailableError` | Exponential backoff | Standard retry |\n\n**Sources:** [openhands/llm/llm.py:44-51](), [openhands/llm/retry_mixin.py:15-101]()",
"Debug and Logging": "The `DebugMixin` provides comprehensive logging for troubleshooting:\n\n['**Prompt Logging**: Full conversation history with message formatting', '**Response Logging**: Model responses including tool calls', '**Content Formatting**: Handles both text and image content appropriately']\n\n**Sources:** [openhands/llm/debug_mixin.py:13-74]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
},
{
"title": "Runtime & Execution Environment",
"description": null,
"content": {
"Runtime Architecture Overview": "The runtime system follows a client-server architecture where the OpenHands backend communicates with sandboxed execution environments through HTTP APIs.",
"Runtime Architecture": "```\ngraph TB\n subgraph \"OpenHands Backend\"\n Agent[\"Agent Controller\"]\n Runtime[\"Runtime (Base Class)\"]\n end\n \n subgraph \"Runtime Implementations\"\n DockerRuntime[\"DockerRuntime\"]\n RemoteRuntime[\"RemoteRuntime\"]\n ActionExecutionClient[\"ActionExecutionClient\"]\n end\n \n subgraph \"Sandbox Environment\"\n ActionExecutor[\"ActionExecutor\"]\n BashSession[\"BashSession\"]\n JupyterPlugin[\"JupyterPlugin\"]\n VSCodePlugin[\"VSCodePlugin\"]\n Browser[\"BrowserEnv\"]\n end\n \n Agent --> Runtime\n Runtime --> DockerRuntime\n Runtime --> RemoteRuntime\n DockerRuntime --> ActionExecutionClient\n RemoteRuntime --> ActionExecutionClient\n ActionExecutionClient -->|HTTP API| ActionExecutor\n ActionExecutor --> BashSession\n ActionExecutor --> JupyterPlugin\n ActionExecutor --> VSCodePlugin\n ActionExecutor --> Browser\n```\n\nSources: [openhands/runtime/base.py:90-117](), [openhands/runtime/impl/docker/docker_runtime.py:75-86](), [openhands/runtime/impl/remote/remote_runtime.py:39-40](), [openhands/runtime/impl/action_execution/action_execution_client.py:61-66](), [openhands/runtime/action_execution_server.py:166-169]()",
"Runtime Types and Implementations": {
"DockerRuntime": "`DockerRuntime` creates Docker containers with the runtime environment and communicates with an `ActionExecutor` running inside the container. It handles container lifecycle, port mapping, volume mounts, and network configuration.\n\nKey features:\n\n['Automatic container image building from base images', 'Port allocation and forwarding for VSCode and application access', 'Volume mounting for workspace persistence', 'GPU support when enabled', 'Network isolation and additional network connections']\n\nSources: [openhands/runtime/impl/docker/docker_runtime.py:75-158]()",
"RemoteRuntime": "`RemoteRuntime` connects to remote execution environments managed by a Remote Runtime API. This enables cloud-based sandboxed execution with features like auto-scaling and resource management.\n\nKey features:\n\n['API-based runtime provisioning and management', 'Automatic runtime resumption from paused state', 'Resource scaling based on configuration', 'Session persistence across connections']\n\nSources: [openhands/runtime/impl/remote/remote_runtime.py:39-107]()"
},
"Action Execution Flow": "The action execution system processes agent actions through a well-defined pipeline from the agent to the sandboxed environment.",
"Action Execution Pipeline": {
"Action Types and Execution": "The `ActionExecutor` handles different action types through specialized methods:\n\n['**`CmdRunAction`**: Executes bash commands via `BashSession` or `WindowsPowershellSession`', '**`IPythonRunCellAction`**: Runs Python code through `JupyterPlugin`', '**`FileReadAction`** / **`FileWriteAction`**: File system operations with security checks', '**`FileEditAction`**: File editing using `OHEditor` with diff tracking', '**`BrowseURLAction`** / **`BrowseInteractiveAction`**: Web browsing through `BrowserEnv`']\n\nSources: [openhands/runtime/action_execution_server.py:385-643]()"
},
"Sandbox Environment Configuration": {
"Key Configuration Options": "| Setting | Purpose | Default |\n|---------|---------|---------|\n| `timeout` | Action execution timeout | 120 seconds |\n| `user_id` | Sandbox user ID | 1000 |\n| `base_container_image` | Base Docker image | `nikolaik/python-nodejs` |\n| `runtime_extra_deps` | Additional dependencies | None |\n| `enable_auto_lint` | Auto-lint files after editing | False |\n| `browsergym_eval_env` | Browser evaluation environment | None |\n| `volumes` | Volume mount configuration | None |\n\nSources: [openhands/core/config/sandbox_config.py:8-95]()",
"Runtime Initialization": "Runtime initialization follows a consistent pattern across implementations:\n\n['**Environment Setup**: Configure environment variables and user settings', '**Plugin Loading**: Initialize plugins like Jupyter, VSCode, and browser support', '**Tool Preparation**: Set up bash session, file editor, and other tools', '**Status Reporting**: Update runtime status through callback functions']\n\nSources: [openhands/runtime/action_execution_server.py:291-323]()"
},
"Runtime Lifecycle Management": {
"Startup Process": "```\ngraph TD\n subgraph \"Runtime Startup\"\n Config[\"Load SandboxConfig\"]\n Image[\"Build/Pull Container Image\"]\n Container[\"Start Container/Remote Instance\"]\n Server[\"Start ActionExecutor Server\"]\n Plugins[\"Initialize Plugins\"]\n Ready[\"Runtime Ready\"]\n end\n \n Config --> Image\n Image --> Container\n Container --> Server\n Server --> Plugins\n Plugins --> Ready\n```\n\nSources: [openhands/runtime/impl/docker/docker_runtime.py:170-215](), [openhands/runtime/impl/remote/remote_runtime.py:125-172]()",
"Runtime Status Management": "The runtime system tracks execution state through `RuntimeStatus` enumeration:\n\n['`STARTING_RUNTIME`: Runtime is being initialized', '`BUILDING_RUNTIME`: Container image is being built', '`RUNTIME_STARTED`: Runtime is active but not ready', '`READY`: Runtime is ready to execute actions', '`ERROR`: Runtime encountered an error', '`ERROR_RUNTIME_DISCONNECTED`: Communication lost with runtime']\n\nStatus changes are communicated through callback functions to provide real-time feedback to users.\n\nSources: [openhands/runtime/runtime_status.py](), [openhands/runtime/base.py:235-241]()",
"Connection Management and Recovery": "The runtime system includes robust connection management:\n\n['**Health Checks**: Regular `/alive` endpoint checks to verify runtime connectivity', '**Retry Logic**: Automatic retry with exponential backoff for recoverable errors', '**Runtime Resumption**: Automatic resumption of paused remote runtimes', '**Error Handling**: Graceful degradation and error reporting']\n\nSources: [openhands/runtime/impl/action_execution/action_execution_client.py:131-138](), [openhands/runtime/impl/remote/remote_runtime.py:403-476]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
},
{
"title": "Frontend & User Interfaces",
"description": null,
"content": {
"Architecture Overview": "OpenHands provides multiple user interface options to accommodate different user preferences and use cases. The system supports both graphical and text-based interactions through a unified backend API.",
"Frontend Architecture Components": "```\ngraph TB\n subgraph \"User Interfaces\"\n WEB[\"React Web App<br/>frontend/\"]\n CLI[\"CLI Interface<br/>openhands/cli/\"]\n end\n \n subgraph \"Communication Layer\"\n API_CLIENT[\"OpenHands API Client<br/>open-hands.ts\"]\n WS_CLIENT[\"WebSocket Client<br/>Real-time Events\"]\n HTTP_CLIENT[\"HTTP Client<br/>REST Endpoints\"]\n end\n \n subgraph \"State Management\"\n REDUX[\"Redux Store<br/>State Management\"]\n SETTINGS_STORE[\"Settings Store<br/>Local Configuration\"]\n REACT_QUERY[\"React Query<br/>Server State\"]\n end\n \n subgraph \"Backend Services\"\n FASTAPI[\"FastAPI Server<br/>REST + WebSocket\"]\n EVENT_STREAM[\"EventStream<br/>Real-time Communication\"]\n end\n \n WEB --> API_CLIENT\n CLI --> HTTP_CLIENT\n \n API_CLIENT --> WS_CLIENT\n API_CLIENT --> HTTP_CLIENT\n API_CLIENT --> REACT_QUERY\n \n WEB --> REDUX\n WEB --> SETTINGS_STORE\n CLI --> SETTINGS_STORE\n \n WS_CLIENT --> EVENT_STREAM\n HTTP_CLIENT --> FASTAPI\n \n REACT_QUERY --> FASTAPI\n```\n\n**Sources:** [frontend/src/api/open-hands.ts:1-501](), [openhands/cli/main.py:1-644](), [openhands/cli/tui.py:1-1016](), [frontend/src/hooks/query/use-settings.ts:1-91]()",
"Web Frontend System": {
"Core Web Components": "```\ngraph TD\n subgraph \"React Application\"\n APP[\"App Component\"]\n ROUTES[\"Route Components<br/>app-settings.tsx<br/>llm-settings.tsx\"]\n COMPONENTS[\"UI Components<br/>Settings Forms<br/>Chat Interface\"]\n end\n \n subgraph \"State Management\"\n REDUX_STORE[\"Redux Store<br/>Application State\"]\n REACT_QUERY_CLIENT[\"React Query Client<br/>useSettings<br/>useSaveSettings\"]\n SETTINGS_HOOK[\"useSettings Hook<br/>use-settings.ts\"]\n end\n \n subgraph \"API Integration\"\n OPEN_HANDS_CLIENT[\"OpenHands Class<br/>Static Methods\"]\n SETTINGS_SERVICE[\"SettingsService<br/>API Endpoints\"]\n WS_COMMUNICATION[\"WebSocket Events<br/>Real-time Updates\"]\n end\n \n subgraph \"Internationalization\"\n I18N_SYSTEM[\"i18n System<br/>translation.json\"]\n LANGUAGE_SUPPORT[\"Multi-language Support<br/>16 Languages\"]\n end\n \n APP --> ROUTES\n ROUTES --> COMPONENTS\n COMPONENTS --> REDUX_STORE\n COMPONENTS --> REACT_QUERY_CLIENT\n \n REACT_QUERY_CLIENT --> SETTINGS_HOOK\n SETTINGS_HOOK --> OPEN_HANDS_CLIENT\n OPEN_HANDS_CLIENT --> SETTINGS_SERVICE\n OPEN_HANDS_CLIENT --> WS_COMMUNICATION\n \n COMPONENTS --> I18N_SYSTEM\n I18N_SYSTEM --> LANGUAGE_SUPPORT\n```\n\n**Sources:** [frontend/src/api/open-hands.ts:24-500](), [frontend/src/hooks/query/use-settings.ts:10-91](), [frontend/src/hooks/mutation/use-save-settings.ts:1-78](), [frontend/src/routes/app-settings.tsx:1-265](), [frontend/src/i18n/translation.json:1-50]()\n\nThe web frontend uses React Query for server state management, with hooks like `useSettings()` and `useSaveSettings()` providing reactive data binding. The `OpenHands` class serves as the main API client, exposing static methods for all backend communication."
},
"Command Line Interface System": {
"CLI Architecture Components": "```\ngraph TD\n subgraph \"CLI Entry Points\"\n MAIN[\"main.py<br/>run_session()\"]\n COMMANDS[\"commands.py<br/>handle_commands()\"]\n end\n \n subgraph \"Terminal UI\"\n TUI[\"tui.py<br/>Terminal Interface\"]\n DISPLAY_FUNCTIONS[\"Display Functions<br/>display_event()<br/>display_banner()\"]\n INPUT_FUNCTIONS[\"Input Functions<br/>read_prompt_input()<br/>cli_confirm()\"]\n end\n \n subgraph \"CLI Settings\"\n SETTINGS_CLI[\"settings.py<br/>modify_llm_settings_basic()\"]\n FILE_SETTINGS_STORE[\"FileSettingsStore<br/>Persistent Storage\"]\n end\n \n subgraph \"Agent Communication\"\n EVENT_STREAM[\"EventStream<br/>Real-time Events\"]\n AGENT_CONTROLLER[\"AgentController<br/>Agent Management\"]\n end\n \n MAIN --> COMMANDS\n MAIN --> TUI\n COMMANDS --> SETTINGS_CLI\n \n TUI --> DISPLAY_FUNCTIONS\n TUI --> INPUT_FUNCTIONS\n \n SETTINGS_CLI --> FILE_SETTINGS_STORE\n \n MAIN --> EVENT_STREAM\n EVENT_STREAM --> AGENT_CONTROLLER\n \n DISPLAY_FUNCTIONS --> EVENT_STREAM\n```\n\n**Sources:** [openhands/cli/main.py:91-644](), [openhands/cli/tui.py:79-1016](), [openhands/cli/commands.py:122-174](), [openhands/cli/settings.py:1-566]()\n\nThe CLI uses an event-driven architecture where `display_event()` handles real-time updates from the agent, while command processing through `handle_commands()` manages user interactions and system control."
},
"API Communication Layer": {
"OpenHands API Client Structure": "| Method Category | Key Methods | Purpose |\n|---|---|---|\n| **Conversation Management** | `createConversation()`, `getConversation()`, `updateConversation()` | CRUD operations for conversations |\n| **Session Control** | `startConversation()`, `stopConversation()` | Agent lifecycle management |\n| **File Operations** | `getFiles()`, `getFile()`, `uploadFiles()` | Workspace file management |\n| **Real-time Communication** | `getConversationHeaders()`, WebSocket integration | Live agent interaction |\n| **Feedback System** | `submitFeedback()`, `getBatchFeedback()` | User feedback collection |\n\n**Sources:** [frontend/src/api/open-hands.ts:67-500](), [frontend/src/api/open-hands.types.ts:1-142]()\n\nThe `OpenHands` class provides static methods for all API operations, with automatic session management through `currentConversation` state and authentication headers via `getConversationHeaders()`."
},
"Settings and Configuration Management": {
"Settings Architecture": "```\ngraph LR\n subgraph \"Frontend Settings\"\n WEB_SETTINGS[\"Web Settings Forms<br/>app-settings.tsx<br/>llm-settings.tsx\"]\n SETTINGS_HOOKS[\"React Hooks<br/>useSettings<br/>useSaveSettings\"]\n end\n \n subgraph \"CLI Settings\"\n CLI_SETTINGS[\"CLI Settings<br/>settings.py\"]\n CLI_COMMANDS[\"Settings Commands<br/>/settings command\"]\n end\n \n subgraph \"Settings Storage\"\n DEFAULT_SETTINGS[\"DEFAULT_SETTINGS<br/>services/settings.ts\"]\n API_SETTINGS[\"ApiSettings<br/>Backend Storage\"]\n FILE_SETTINGS[\"FileSettingsStore<br/>Local Config Files\"]\n end\n \n subgraph \"Configuration Types\"\n SETTINGS_TYPE[\"Settings Type<br/>types/settings.ts\"]\n MCP_CONFIG[\"MCPConfig<br/>MCP Server Configuration\"]\n POST_SETTINGS[\"PostSettings<br/>API Request Format\"]\n end\n \n WEB_SETTINGS --> SETTINGS_HOOKS\n CLI_SETTINGS --> CLI_COMMANDS\n \n SETTINGS_HOOKS --> DEFAULT_SETTINGS\n CLI_COMMANDS --> FILE_SETTINGS\n \n DEFAULT_SETTINGS --> API_SETTINGS\n FILE_SETTINGS --> API_SETTINGS\n \n API_SETTINGS --> SETTINGS_TYPE\n SETTINGS_TYPE --> MCP_CONFIG\n SETTINGS_TYPE --> POST_SETTINGS\n```\n\n**Sources:** [frontend/src/services/settings.ts:1-40](), [frontend/src/types/settings.ts:1-72](), [openhands/cli/settings.py:41-566](), [openhands/storage/data_models/settings.py:21-187]()\n\nSettings are managed through a layered system where `DEFAULT_SETTINGS` provides fallback values, while user modifications are persisted via API endpoints or local file storage depending on the interface used."
},
"Internationalization System": {
"Translation System Structure": "| Component | File | Purpose |\n|---|---|---|\n| **Translation Data** | `frontend/src/i18n/translation.json` | Complete translation database |\n| **Type Declarations** | `frontend/src/i18n/declaration.ts` | TypeScript enum for translation keys |\n| **Language Support** | React i18next integration | Runtime language switching |\n\nThe i18n system uses a hierarchical key structure like `SETTINGS$LLM_API_KEY` and `MICROAGENT$ADD_TO_MICROAGENT`, providing type-safe access to translations through the `I18nKey` enum.\n\n**Sources:** [frontend/src/i18n/translation.json:1-5986](), [frontend/src/i18n/declaration.ts:1-598]()"
},
"Authentication and Session Management": {
"Session Management Components": [
"**Conversation Sessions**: Each conversation gets a unique `conversation_id` and optional `session_api_key`",
"**Authentication Headers**: Managed through `getConversationHeaders()` in the API client",
"**Session State**: Tracked through `currentConversation` in the OpenHands class",
"**Settings Integration**: User authentication status affects settings availability"
]
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": [
{
"title": "Web Interface & API",
"description": null,
"content": {
"Architecture Overview": "The web interface follows a client-server architecture with real-time communication capabilities:\n\n```\ngraph TB\n subgraph \"Frontend (React)\"\n UI[\"React Components\"]\n API_CLIENT[\"OpenHands API Client\"]\n WS_CLIENT[\"WebSocket Client\"]\n REDUX[\"Redux Store\"]\n end\n \n subgraph \"Backend (FastAPI)\"\n FASTAPI_APP[\"FastAPI Application\"]\n SOCKETIO[\"Socket.IO Server\"]\n ROUTES[\"API Routes\"]\n MIDDLEWARE[\"Middleware Stack\"]\n end\n \n subgraph \"Core Services\"\n CONV_MGR[\"ConversationManager\"]\n EVENT_STORE[\"EventStore\"]\n SETTINGS_STORE[\"SettingsStore\"]\n SECRETS_STORE[\"SecretsStore\"]\n end\n \n UI --> API_CLIENT\n UI --> WS_CLIENT\n UI --> REDUX\n \n API_CLIENT -->|\"HTTP REST\"| FASTAPI_APP\n WS_CLIENT -->|\"WebSocket\"| SOCKETIO\n \n FASTAPI_APP --> ROUTES\n FASTAPI_APP --> MIDDLEWARE\n ROUTES --> CONV_MGR\n ROUTES --> EVENT_STORE\n ROUTES --> SETTINGS_STORE\n ROUTES --> SECRETS_STORE\n \n SOCKETIO --> CONV_MGR\n```\n\nSources: [frontend/src/api/open-hands.ts](), [openhands/server/app.py](), [openhands/server/listen.py](), [frontend/src/context/ws-client-provider.tsx]()",
"Frontend Architecture": {
"Core Frontend Components": "```\ngraph TD\n subgraph \"API Layer\"\n OPEN_HANDS_API[\"OpenHands Class\"]\n WS_PROVIDER[\"WsClientProvider\"]\n SETTINGS_API[\"SettingsService\"]\n end\n \n subgraph \"State Management\"\n QUERY_CLIENT[\"React Query\"]\n REDUX_STORE[\"Redux Store\"]\n CONTEXT_PROVIDERS[\"Context Providers\"]\n end\n \n subgraph \"UI Components\"\n APP_ROUTE[\"App Routes\"]\n CONVERSATION[\"ConversationMain\"]\n SETTINGS_UI[\"Settings Screens\"]\n CHAT_INTERFACE[\"ChatInterface\"]\n end\n \n OPEN_HANDS_API --> QUERY_CLIENT\n WS_PROVIDER --> REDUX_STORE\n SETTINGS_API --> QUERY_CLIENT\n \n QUERY_CLIENT --> UI_COMPONENTS\n REDUX_STORE --> UI_COMPONENTS\n CONTEXT_PROVIDERS --> UI_COMPONENTS\n \n APP_ROUTE --> CONVERSATION\n APP_ROUTE --> SETTINGS_UI\n CONVERSATION --> CHAT_INTERFACE\n```\n\nThe `OpenHands` class in [frontend/src/api/open-hands.ts:24-500]() serves as the primary API client, providing methods for all backend communication. Key methods include:\n\n['`createConversation()` - Creates new conversations', '`getConversation()` - Retrieves conversation details ', '`submitFeedback()` - Submits user feedback', '`getFiles()` - Lists workspace files', '`uploadFiles()` - Uploads files to workspace']\n\nThe `WsClientProvider` in [frontend/src/context/ws-client-provider.tsx:130-397]() manages WebSocket connections and real-time event handling.\n\nSources: [frontend/src/api/open-hands.ts](), [frontend/src/context/ws-client-provider.tsx](), [frontend/src/routes/conversation.tsx]()",
"Settings Management": "The frontend handles user settings through a dedicated API layer:\n\n| Setting Type | Frontend Hook | Backend Route |\n|--------------|---------------|---------------|\n| LLM Configuration | `useSettings()` | `/api/settings` |\n| Provider Tokens | `useSaveSettings()` | `/api/add-git-providers` |\n| Custom Secrets | Custom hooks | `/api/secrets/*` |\n| MCP Configuration | Settings form | `/api/settings` |\n\nSources: [frontend/src/hooks/query/use-settings.ts](), [frontend/src/hooks/mutation/use-save-settings.ts](), [frontend/src/routes/app-settings.tsx]()"
},
"Backend API Architecture ": {
"FastAPI Application Structure": "```\ngraph TD\n subgraph \"FastAPI App\"\n BASE_APP[\"FastAPI base_app\"]\n SOCKETIO_APP[\"Socket.IO ASGIApp\"]\n STATIC_FILES[\"SPAStaticFiles\"]\n end\n \n subgraph \"Routers\"\n CONVERSATION_ROUTER[\"conversation_api_router\"]\n SETTINGS_ROUTER[\"settings_router\"]\n SECRETS_ROUTER[\"secrets_router\"]\n FILES_ROUTER[\"files_api_router\"]\n FEEDBACK_ROUTER[\"feedback_api_router\"]\n SECURITY_ROUTER[\"security_api_router\"]\n GIT_ROUTER[\"git_api_router\"]\n end\n \n subgraph \"Middleware\"\n CORS[\"LocalhostCORSMiddleware\"]\n CACHE[\"CacheControlMiddleware\"]\n RATE_LIMIT[\"RateLimitMiddleware\"]\n end\n \n BASE_APP --> CONVERSATION_ROUTER\n BASE_APP --> SETTINGS_ROUTER\n BASE_APP --> SECRETS_ROUTER\n BASE_APP --> FILES_ROUTER\n BASE_APP --> FEEDBACK_ROUTER\n BASE_APP --> SECURITY_ROUTER\n BASE_APP --> GIT_ROUTER\n \n BASE_APP --> CORS\n BASE_APP --> CACHE\n BASE_APP --> RATE_LIMIT\n \n SOCKETIO_APP --> BASE_APP\n BASE_APP --> STATIC_FILES\n```\n\nThe main application is defined in [openhands/server/app.py:58-64]() and includes routers for different functional areas. The Socket.IO integration is handled in [openhands/server/listen.py:27]().\n\nSources: [openhands/server/app.py](), [openhands/server/listen.py](), [openhands/server/middleware.py]()",
"Key API Endpoints": "| Endpoint Pattern | Router | Purpose |\n|------------------|--------|---------|\n| `/api/conversations/*` | `conversation_api_router` | Conversation management |\n| `/api/settings` | `settings_router` | User settings CRUD |\n| `/api/secrets/*` | `secrets_router` | Secrets management | \n| `/api/files/*` | `files_api_router` | File operations |\n| `/feedback/*` | `feedback_api_router` | User feedback |\n| `/api/security/*` | `security_api_router` | Security analysis |",
"Settings API Implementation": "The settings system handles user configuration through multiple endpoints:\n\n```\ngraph LR\n subgraph \"Settings Flow\"\n GET_SETTINGS[\"/api/settings GET\"]\n POST_SETTINGS[\"/api/settings POST\"]\n LOAD_SETTINGS[\"load_settings()\"]\n STORE_SETTINGS[\"store_settings()\"]\n end\n \n subgraph \"Data Models\"\n SETTINGS[\"Settings\"]\n GET_SETTINGS_MODEL[\"GETSettingsModel\"]\n USER_SECRETS[\"UserSecrets\"]\n end\n \n subgraph \"Storage\"\n SETTINGS_STORE[\"SettingsStore\"]\n SECRETS_STORE[\"SecretsStore\"]\n end\n \n GET_SETTINGS --> LOAD_SETTINGS\n POST_SETTINGS --> STORE_SETTINGS\n \n LOAD_SETTINGS --> GET_SETTINGS_MODEL\n STORE_SETTINGS --> SETTINGS\n \n LOAD_SETTINGS --> SETTINGS_STORE\n LOAD_SETTINGS --> SECRETS_STORE\n STORE_SETTINGS --> SETTINGS_STORE\n \n GET_SETTINGS_MODEL --> USER_SECRETS\n```\n\nThe `load_settings` function in [openhands/server/routes/settings.py:36-87]() handles GET requests and includes provider token validation. The `store_settings` function in [openhands/server/routes/settings.py:141-192]() processes POST requests and updates configuration.\n\nSources: [openhands/server/routes/settings.py](), [openhands/server/settings.py](), [openhands/storage/data_models/settings.py]()"
},
"WebSocket Communication": {
"WebSocket Event Flow": "```\nsequenceDiagram\n participant Frontend as \"WsClientProvider\"\n participant Backend as \"Socket.IO Server\"\n participant ConvMgr as \"ConversationManager\"\n participant EventStore as \"EventStore\"\n \n Frontend->>Backend: connect(conversation_id, latest_event_id)\n Backend->>EventStore: replay events from latest_event_id\n EventStore-->>Backend: event stream\n Backend->>Frontend: oh_event (for each event)\n \n Frontend->>Backend: oh_user_action(user_input)\n Backend->>ConvMgr: send_to_event_stream(data)\n ConvMgr->>EventStore: store event\n ConvMgr-->>Backend: agent_response\n Backend->>Frontend: oh_event(agent_response)\n```",
"Socket.IO Event Handlers": "The main Socket.IO handlers are defined in [openhands/server/listen_socket.py]():\n\n['`connect()` - Handles client connections and event replay from [openhands/server/listen_socket.py:36-141]()', '`oh_user_action()` - Processes user actions from [openhands/server/listen_socket.py:144-145]() ', '`disconnect()` - Handles client disconnections from [openhands/server/listen_socket.py:156-158]()']\n\nThe frontend WebSocket client in [frontend/src/context/ws-client-provider.tsx:151-157]() sends events via the `send()` method using the `oh_user_action` event type.\n\nSources: [openhands/server/listen_socket.py](), [frontend/src/context/ws-client-provider.tsx]()",
"Event Processing Pipeline": "The frontend processes incoming WebSocket events through several stages:\n\n```\ngraph TD\n WS_EVENT[\"WebSocket Event\"]\n EVENT_VALIDATION[\"Event Validation\"]\n EVENT_PARSING[\"Event Parsing\"]\n STATE_UPDATE[\"State Updates\"]\n UI_UPDATE[\"UI Updates\"]\n \n WS_EVENT --> EVENT_VALIDATION\n EVENT_VALIDATION --> EVENT_PARSING\n EVENT_PARSING --> STATE_UPDATE\n STATE_UPDATE --> UI_UPDATE\n \n subgraph \"Event Types\"\n USER_MSG[\"UserMessageAction\"]\n ASSISTANT_MSG[\"AssistantMessageAction\"] \n FILE_EDIT[\"FileEditAction\"]\n COMMAND[\"CommandAction\"]\n AGENT_STATE[\"AgentStateChangedObservation\"]\n end\n \n EVENT_PARSING --> USER_MSG\n EVENT_PARSING --> ASSISTANT_MSG\n EVENT_PARSING --> FILE_EDIT\n EVENT_PARSING --> COMMAND\n EVENT_PARSING --> AGENT_STATE\n```\n\nEvent processing is handled in the `handleMessage` function at [frontend/src/context/ws-client-provider.tsx:164-256](), which includes validation, state updates, and cache invalidation logic.\n\nSources: [frontend/src/context/ws-client-provider.tsx](), [frontend/src/types/core/guards.ts]()"
},
"Authentication and Security": {
"Middleware Stack": "| Middleware | Purpose | Implementation |\n|------------|---------|----------------|\n| `LocalhostCORSMiddleware` | CORS handling with localhost allowances | [openhands/server/middleware.py:16-48]() |\n| `CacheControlMiddleware` | Cache control headers | [openhands/server/middleware.py:51-67]() |\n| `RateLimitMiddleware` | Request rate limiting | [openhands/server/middleware.py:108-131]() |",
"User Authentication": "The authentication system is extensible through the `UserAuth` abstract base class in [openhands/server/user_auth/user_auth.py:23-89](). The default implementation `DefaultUserAuth` in [openhands/server/user_auth/default_user_auth.py:16-79]() provides basic single-user functionality.\n\nAuthentication helpers are provided through dependency injection:\n\n['`get_user_settings()` - Retrieves user settings', '`get_provider_tokens()` - Gets provider authentication tokens ', '`get_secrets_store()` - Accesses user secrets']\n\nSources: [openhands/server/middleware.py](), [openhands/server/user_auth/user_auth.py](), [openhands/server/user_auth/default_user_auth.py](), [openhands/server/user_auth/__init__.py]()"
},
"File Operations and Workspace Management": {
"File API Endpoints": "```\ngraph LR\n subgraph \"File Operations\"\n LIST_FILES[\"GET /list-files\"]\n SELECT_FILE[\"GET /select-file\"] \n UPLOAD_FILES[\"POST /upload-files\"]\n SAVE_FILE[\"POST /save-file\"]\n end\n \n subgraph \"Frontend Hooks\"\n USE_FILES[\"useGetFiles()\"]\n USE_FILE_CONTENT[\"useGetFile()\"] \n UPLOAD_HOOK[\"uploadFiles()\"]\n end\n \n subgraph \"Backend Implementation\"\n GET_FILES_IMPL[\"getFiles()\"]\n GET_FILE_IMPL[\"getFile()\"]\n UPLOAD_IMPL[\"uploadFiles()\"]\n end\n \n LIST_FILES --> GET_FILES_IMPL\n SELECT_FILE --> GET_FILE_IMPL\n UPLOAD_FILES --> UPLOAD_IMPL\n \n USE_FILES --> LIST_FILES\n USE_FILE_CONTENT --> SELECT_FILE\n UPLOAD_HOOK --> UPLOAD_FILES\n```\n\nThe `OpenHands` class provides file operation methods:\n\n['`getFiles()` at [frontend/src/api/open-hands.ts:442-453]() - Lists workspace files', '`getFile()` at [frontend/src/api/open-hands.ts:461-469]() - Retrieves file content', '`uploadFiles()` at [frontend/src/api/open-hands.ts:477-497]() - Uploads multiple files']\n\nSources: [frontend/src/api/open-hands.ts](), [openhands/server/routes/files.py]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
},
{
"title": "Command Line Interface",
"description": null,
"content": {
"CLI Architecture Overview": "The CLI system consists of several interconnected components that handle user interaction, agent orchestration, and session management:\n\n```\ngraph TB\n subgraph \"CLI Entry Point\"\n RCC[\"run_cli_command()\"]\n MWL[\"main_with_loop()\"]\n end\n \n subgraph \"Session Management\"\n RS[\"run_session()\"]\n CS[\"cleanup_session()\"]\n RSF[\"run_setup_flow()\"]\n end\n \n subgraph \"User Interface\"\n TUI[\"TUI Display Functions\"]\n PI[\"Prompt Input System\"]\n CC[\"CommandCompleter\"]\n CLI_CONFIRM[\"cli_confirm()\"]\n end\n \n subgraph \"Command Processing\"\n HC[\"handle_commands()\"]\n REPL[\"Command REPL Loop\"]\n CMD_HANDLERS[\"Command Handlers\"]\n end\n \n subgraph \"Configuration\"\n SETTINGS[\"Settings Management\"]\n CONFIG_LOAD[\"Config Loading\"]\n FILE_STORE[\"FileSettingsStore\"]\n end\n \n subgraph \"Agent Integration\" \n AC[\"AgentController\"]\n ES[\"EventStream\"]\n RT[\"Runtime\"]\n MEM[\"Memory\"]\n end\n \n RCC --> MWL\n MWL --> RSF\n MWL --> RS\n RS --> TUI\n RS --> PI\n RS --> HC\n HC --> CMD_HANDLERS\n HC --> REPL\n TUI --> CLI_CONFIRM\n PI --> CC\n MWL --> SETTINGS\n SETTINGS --> FILE_STORE\n RS --> AC\n RS --> ES\n RS --> RT\n RS --> MEM\n RS --> CS\n```\n\n**CLI System Architecture**\n\nThe CLI operates through a main event loop that coordinates user input, agent execution, and output rendering through a sophisticated terminal user interface.\n\nSources: [openhands/cli/main.py:758-781](), [openhands/cli/main.py:565-756](), [openhands/cli/tui.py:1-40]()",
"Core CLI Components": {
"Main Entry Point and Session Management": "The CLI entry point is handled by `run_cli_command` which sets up the event loop and manages the overall CLI lifecycle:\n\n```\ngraph TD\n subgraph \"CLI Startup Flow\"\n ENTRY[\"run_cli_command()\"] \n LOOP[\"asyncio.new_event_loop()\"]\n MAIN_LOOP[\"main_with_loop()\"]\n CONFIG_SETUP[\"setup_config_from_args()\"]\n SETTINGS_LOAD[\"FileSettingsStore.get_instance()\"]\n end\n \n subgraph \"Setup Flows\"\n SETUP_FLOW[\"run_setup_flow()\"]\n ALIAS_FLOW[\"run_alias_setup_flow()\"]\n SECURITY_CHECK[\"check_folder_security_agreement()\"]\n end\n \n subgraph \"Session Execution\"\n RUN_SESSION[\"run_session()\"]\n SESSION_LOOP[\"Agent Session Loop\"]\n CLEANUP[\"cleanup_session()\"]\n end\n \n ENTRY --> LOOP\n LOOP --> MAIN_LOOP\n MAIN_LOOP --> CONFIG_SETUP\n MAIN_LOOP --> SETTINGS_LOAD\n MAIN_LOOP --> SETUP_FLOW\n MAIN_LOOP --> ALIAS_FLOW\n MAIN_LOOP --> SECURITY_CHECK\n MAIN_LOOP --> RUN_SESSION\n RUN_SESSION --> SESSION_LOOP\n SESSION_LOOP --> CLEANUP\n \n style RUN_SESSION fill:#f9f\n style SESSION_LOOP fill:#f9f\n```\n\n**CLI Startup and Session Flow**\n\nThe session management handles agent lifecycle, conversation persistence, and cleanup through coordinated async operations.\n\nSources: [openhands/cli/main.py:758-781](), [openhands/cli/main.py:565-756](), [openhands/cli/main.py:125-444]()",
"Terminal User Interface System": "The TUI system provides rich terminal output and interactive input handling through the `prompt_toolkit` library:\n\n| Component | Function | Description |\n|-----------|----------|-------------|\n| **Display Functions** | `display_event()` | Routes events to appropriate display handlers |\n| **Input System** | `read_prompt_input()` | Handles user input with command completion |\n| **Confirmation UI** | `cli_confirm()` | Interactive choice selection with keyboard navigation |\n| **Command Completion** | `CommandCompleter` | Auto-completion for CLI commands |\n| **Streaming Output** | `update_streaming_output()` | Real-time command output display |\n| **Styled Output** | `get_cli_style()` | Terminal styling and color management |\n\nThe event display system handles different event types through specialized display functions:\n\n```\ngraph LR\n subgraph \"Event Display Routing\"\n DE[\"display_event()\"]\n CRA[\"CmdRunAction\"]\n MA[\"MessageAction\"] \n CO[\"CmdOutputObservation\"]\n FE[\"FileEditObservation\"]\n FR[\"FileReadObservation\"]\n MCP_A[\"MCPAction\"]\n MCP_O[\"MCPObservation\"]\n end\n \n subgraph \"Display Handlers\"\n DC[\"display_command()\"]\n DCO[\"display_command_output()\"]\n DFE[\"display_file_edit()\"]\n DFR[\"display_file_read()\"]\n DM[\"display_message()\"]\n DMCP_A[\"display_mcp_action()\"]\n DMCP_O[\"display_mcp_observation()\"]\n end\n \n DE --> CRA\n DE --> MA\n DE --> CO\n DE --> FE\n DE --> FR\n DE --> MCP_A\n DE --> MCP_O\n \n CRA --> DC\n CO --> DCO\n FE --> DFE\n FR --> DFR\n MA --> DM\n MCP_A --> DMCP_A\n MCP_O --> DMCP_O\n```\n\n**TUI Event Display System**\n\nSources: [openhands/cli/tui.py:260-305](), [openhands/cli/tui.py:384-587](), [openhands/cli/pt_style.py:13-28]()"
},
"Interactive Command System": {
"Command Processing Flow": "```\ngraph TD\n subgraph \"Command Input\"\n RPI[\"read_prompt_input()\"]\n CC[\"CommandCompleter\"]\n USER_INPUT[\"User Input\"]\n end\n \n subgraph \"Command Routing\"\n HC[\"handle_commands()\"]\n CMD_CHECK[\"Command Check\"]\n SLASH_CMD[\"Slash Command\"]\n USER_MSG[\"User Message\"]\n end\n \n subgraph \"Command Handlers\"\n EXIT[\"handle_exit_command()\"]\n HELP[\"handle_help_command()\"]\n INIT[\"handle_init_command()\"]\n STATUS[\"handle_status_command()\"]\n NEW[\"handle_new_command()\"]\n SETTINGS[\"handle_settings_command()\"]\n RESUME[\"handle_resume_command()\"]\n MCP[\"handle_mcp_command()\"]\n end\n \n subgraph \"Event Stream\"\n ES[\"EventStream\"]\n MA[\"MessageAction\"]\n CSA[\"ChangeAgentStateAction\"]\n end\n \n RPI --> USER_INPUT\n CC --> RPI\n USER_INPUT --> HC\n HC --> CMD_CHECK\n CMD_CHECK --> SLASH_CMD\n CMD_CHECK --> USER_MSG\n \n SLASH_CMD --> EXIT\n SLASH_CMD --> HELP\n SLASH_CMD --> INIT\n SLASH_CMD --> STATUS\n SLASH_CMD --> NEW\n SLASH_CMD --> SETTINGS\n SLASH_CMD --> RESUME\n SLASH_CMD --> MCP\n \n USER_MSG --> ES\n EXIT --> CSA\n NEW --> CSA\n USER_MSG --> MA\n```\n\n**Interactive Command Processing**",
"Available Commands": "The CLI supports the following interactive commands:\n\n| Command | Handler Function | Description |\n|---------|------------------|-------------|\n| `/exit` | `handle_exit_command()` | Terminates the current session with confirmation |\n| `/help` | `handle_help_command()` | Displays help information and available commands |\n| `/init` | `handle_init_command()` | Initializes repository with microagent instructions |\n| `/status` | `handle_status_command()` | Shows session status and usage metrics |\n| `/new` | `handle_new_command()` | Creates a new conversation session |\n| `/settings` | `handle_settings_command()` | Opens interactive settings configuration |\n| `/resume` | `handle_resume_command()` | Resumes a paused agent |\n| `/mcp` | `handle_mcp_command()` | Manages MCP server configuration |\n\nSources: [openhands/cli/commands.py:122-173](), [openhands/cli/tui.py:79-88](), [openhands/cli/tui.py:772-795]()"
},
"Configuration and Settings Management": {
"Settings Architecture": "```\ngraph TB\n subgraph \"Configuration Sources\"\n CLI_ARGS[\"Command Line Args\"]\n CONFIG_TOML[\"config.toml\"] \n SETTINGS_JSON[\"settings.json\"]\n ENV_VARS[\"Environment Variables\"]\n end\n \n subgraph \"Settings Management\"\n FSS[\"FileSettingsStore\"]\n SETTINGS_OBJ[\"Settings Object\"]\n CONFIG_OBJ[\"OpenHandsConfig\"]\n end\n \n subgraph \"Interactive Configuration\"\n DS[\"display_settings()\"]\n MLS_BASIC[\"modify_llm_settings_basic()\"]\n MLS_ADV[\"modify_llm_settings_advanced()\"]\n MSA[\"modify_search_api_settings()\"]\n end\n \n subgraph \"Configuration UI\"\n CLI_CONFIRM[\"cli_confirm()\"]\n GVI[\"get_validated_input()\"]\n FUZZY_COMPLETE[\"FuzzyWordCompleter\"]\n end\n \n CLI_ARGS --> CONFIG_OBJ\n CONFIG_TOML --> CONFIG_OBJ\n ENV_VARS --> CONFIG_OBJ\n \n FSS --> SETTINGS_JSON\n FSS --> SETTINGS_OBJ\n SETTINGS_OBJ --> CONFIG_OBJ\n \n DS --> MLS_BASIC\n DS --> MLS_ADV\n DS --> MSA\n \n MLS_BASIC --> CLI_CONFIRM\n MLS_ADV --> GVI\n MSA --> GVI\n \n CLI_CONFIRM --> FUZZY_COMPLETE\n GVI --> FUZZY_COMPLETE\n```\n\n**Settings Management System**",
"Settings Categories": "The CLI settings system manages several configuration categories:\n\n| Category | Configuration Function | Purpose |\n|----------|----------------------|---------|\n| **LLM Basic** | `modify_llm_settings_basic()` | Provider selection, model choice, API keys |\n| **LLM Advanced** | `modify_llm_settings_advanced()` | Custom models, base URLs, advanced options |\n| **Search API** | `modify_search_api_settings()` | Tavily search API configuration |\n| **Agent Settings** | Agent configuration | Default agent, confirmation mode |\n| **Memory Condensation** | Condenser configuration | Memory management settings |\n\nThe settings system uses a hierarchical precedence model where CLI arguments override config files, which override settings.json, which override defaults.\n\nSources: [openhands/cli/settings.py:233-487](), [openhands/cli/settings.py:41-121](), [openhands/cli/commands.py:269-291]()"
},
"MCP Server Integration": {
"MCP Command System": "```\ngraph TD\n subgraph \"MCP Management Interface\"\n MCP_CMD[\"/mcp Command\"]\n MCP_MENU[\"MCP Menu Options\"]\n end\n \n subgraph \"MCP Operations\" \n LIST[\"List Servers\"]\n ADD[\"Add Server\"]\n REMOVE[\"Remove Server\"]\n ERRORS[\"View Errors\"]\n end\n \n subgraph \"Server Types\"\n SSE[\"SSE Servers\"]\n STDIO[\"Stdio Servers\"] \n SHTTP[\"SHTTP Servers\"]\n end\n \n subgraph \"Configuration Management\"\n CONFIG_FILE[\"config.toml\"]\n LOAD_CONFIG[\"load_config_file()\"]\n SAVE_CONFIG[\"save_config_file()\"]\n end\n \n subgraph \"Server Configuration\"\n SSE_CONFIG[\"MCPSSEServerConfig\"]\n STDIO_CONFIG[\"MCPStdioServerConfig\"]\n SHTTP_CONFIG[\"MCPSHTTPServerConfig\"]\n end\n \n MCP_CMD --> MCP_MENU\n MCP_MENU --> LIST\n MCP_MENU --> ADD\n MCP_MENU --> REMOVE\n MCP_MENU --> ERRORS\n \n ADD --> SSE\n ADD --> STDIO\n ADD --> SHTTP\n \n SSE --> SSE_CONFIG\n STDIO --> STDIO_CONFIG\n SHTTP --> SHTTP_CONFIG\n \n ADD --> SAVE_CONFIG\n REMOVE --> LOAD_CONFIG\n REMOVE --> SAVE_CONFIG\n \n SAVE_CONFIG --> CONFIG_FILE\n LOAD_CONFIG --> CONFIG_FILE\n```\n\n**MCP Server Management System**\n\nThe MCP integration supports three transport types:\n\n['**SSE (Server-Sent Events)**: HTTP-based streaming connections', '**Stdio**: Standard input/output process communication ', '**SHTTP**: Streamable HTTP connections']\n\nEach server type has dedicated configuration handlers that validate input and persist settings to `config.toml`.\n\nSources: [openhands/cli/commands.py:431-884](), [openhands/cli/commands.py:507-563](), [openhands/cli/tui.py:199-238]()"
},
"Agent Integration and Event Flow": {
"CLI-Agent Communication Flow": "```\ngraph LR\n subgraph \"CLI Components\"\n USER_INPUT[\"User Input\"]\n PROMPT_TASK[\"prompt_for_next_task()\"]\n ON_EVENT[\"on_event_async()\"]\n end\n \n subgraph \"Event System\"\n ES[\"EventStream\"]\n EVENT_SUB[\"EventStreamSubscriber\"]\n MSG_ACTION[\"MessageAction\"]\n CHANGE_STATE[\"ChangeAgentStateAction\"]\n end\n \n subgraph \"Agent System\"\n AC[\"AgentController\"] \n AGENT[\"Agent\"]\n RT[\"Runtime\"]\n MEM[\"Memory\"]\n end\n \n subgraph \"Agent States\"\n RUNNING[\"RUNNING\"]\n AWAITING_INPUT[\"AWAITING_USER_INPUT\"]\n AWAITING_CONFIRM[\"AWAITING_USER_CONFIRMATION\"]\n PAUSED[\"PAUSED\"]\n FINISHED[\"FINISHED\"]\n end\n \n USER_INPUT --> MSG_ACTION\n MSG_ACTION --> ES\n ES --> AC\n AC --> AGENT\n AGENT --> RT\n \n AC --> EVENT_SUB\n EVENT_SUB --> ON_EVENT\n ON_EVENT --> PROMPT_TASK\n \n ON_EVENT --> AWAITING_INPUT\n ON_EVENT --> AWAITING_CONFIRM\n ON_EVENT --> PAUSED\n ON_EVENT --> FINISHED\n \n AWAITING_CONFIRM --> CHANGE_STATE\n PAUSED --> PROMPT_TASK\n```\n\n**CLI-Agent Event Flow**",
"Session Lifecycle Management": "The CLI manages agent sessions through several key functions:\n\n| Function | Purpose | Key Operations |\n|----------|---------|----------------|\n| `run_session()` | Main session orchestration | Agent creation, runtime setup, event handling |\n| `cleanup_session()` | Session termination | Task cancellation, state persistence, resource cleanup |\n| `on_event_async()` | Event processing | State change handling, user interaction prompts |\n| `prompt_for_next_task()` | User input collection | Command processing, message creation |\n\nThe session system handles agent state transitions and coordinates between user input and agent execution through an event-driven architecture.\n\nSources: [openhands/cli/main.py:125-444](), [openhands/cli/main.py:91-123](), [openhands/cli/main.py:214-310]()"
},
"Security and Confirmation System": {
"Security Architecture": "```\ngraph TD\n subgraph \"Security Checks\"\n FSA[\"check_folder_security_agreement()\"]\n TRUSTED_DIRS[\"Trusted Directories\"]\n CONFIRM_MODE[\"Confirmation Mode\"]\n end\n \n subgraph \"Action Security Assessment\"\n ACTION[\"Action\"]\n SEC_RISK[\"ActionSecurityRisk\"]\n HIGH[\"HIGH\"]\n MEDIUM[\"MEDIUM\"] \n LOW[\"LOW\"]\n end\n \n subgraph \"Confirmation Flow\"\n RCI[\"read_confirmation_input()\"]\n CLI_CONFIRM[\"cli_confirm()\"]\n SECURITY_PROMPT[\"Security Prompt\"]\n end\n \n subgraph \"Confirmation Modes\"\n ALWAYS[\"Always Confirm\"]\n AUTO_HIGH[\"Auto High-Risk\"]\n MANUAL[\"Manual Confirm\"]\n end\n \n FSA --> TRUSTED_DIRS\n ACTION --> SEC_RISK\n SEC_RISK --> HIGH\n SEC_RISK --> MEDIUM\n SEC_RISK --> LOW\n \n HIGH --> RCI\n MEDIUM --> RCI\n LOW --> RCI\n \n RCI --> CLI_CONFIRM\n CLI_CONFIRM --> SECURITY_PROMPT\n \n CLI_CONFIRM --> ALWAYS\n CLI_CONFIRM --> AUTO_HIGH\n CLI_CONFIRM --> MANUAL\n```\n\n**Security and Confirmation System**\n\nThe security system includes:\n\n['**Folder Security**: Verification of workspace directory trust', '**Action Risk Assessment**: Classification of actions by security risk level', '**User Confirmation**: Interactive approval for risky operations', '**Confirmation Modes**: Flexible security policies']\n\nSources: [openhands/cli/commands.py:384-428](), [openhands/cli/tui.py:839-869](), [openhands/cli/main.py:245-300]()"
},
"Error Handling and User Experience": {
"Error Display System": "The CLI includes specialized error handling for different components:\n\n| Error Type | Handler | Description |\n|------------|---------|-------------|\n| **MCP Errors** | `display_mcp_errors()` | Shows MCP server connection issues |\n| **Validation Errors** | `ValidationError` handling | Input validation with retry prompts |\n| **Agent Errors** | `ErrorObservation` display | Agent execution error formatting |\n| **Session Errors** | Session error recovery | Handles interrupted sessions and authentication errors |\n\nThe error system provides detailed error messages with actionable guidance and retry mechanisms for recoverable errors.\n\nSources: [openhands/cli/tui.py:199-238](), [openhands/cli/commands.py:636-727](), [openhands/cli/main.py:395-413]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
}
]
},
{
"title": "Integrations",
"description": null,
"content": {
"Git Provider Integration Architecture": {
"Provider Service Architecture": "```\ngraph TB\n subgraph \"Provider Handler Layer\"\n PH[ProviderHandler]\n PT[ProviderToken]\n CS[CustomSecret]\n end\n \n subgraph \"Service Interface\"\n GS[GitService]\n IS[InstallationsService]\n BGS[BaseGitService]\n end\n \n subgraph \"Concrete Implementations\"\n GHS[GitHubService]\n GLS[GitLabService]\n BBS[BitBucketService]\n end\n \n subgraph \"Service Mixins\"\n GHBM[GitHubBranchesMixin]\n GHRM[GitHubReposMixin]\n GHPM[GitHubPRsMixin]\n GHFM[GitHubFeaturesMixin]\n GHREM[GitHubResolverMixin]\n end\n \n subgraph \"HTTP Client Protocol\"\n HC[HTTPClient]\n GHBASE[GitHubMixinBase]\n GLBASE[GitLabMixinBase]\n BBBASE[BitBucketMixinBase]\n end\n \n PH --> GS\n PH --> IS\n GS --> BGS\n \n GHS --> GHBM\n GHS --> GHRM\n GHS --> GHPM\n GHS --> GHFM\n GHS --> GHREM\n GHS --> BGS\n GHS --> GS\n GHS --> IS\n \n GLS --> BGS\n GLS --> GS\n BBS --> BGS\n BBS --> GS\n BBS --> IS\n \n GHBM --> GHBASE\n GHRM --> GHBASE\n GHPM --> GHBASE\n GHFM --> GHBASE\n GHREM --> GHBASE\n \n GHBASE --> HC\n GLBASE --> HC\n BBBASE --> HC\n```\n\nThe `ProviderHandler` class serves as the central orchestrator for all Git provider interactions. It maintains provider tokens and routes requests to appropriate service implementations based on the `ProviderType` enum.\n\nSources: [openhands/integrations/provider.py:105-161](), [openhands/integrations/service_types.py:20-25](), [openhands/integrations/github/github_service.py:21-42]()",
"Service Interface Definition": "The Git provider services implement a common protocol defined by the `GitService` interface, which provides methods for repository operations, user management, and microagent handling:\n\n```\ngraph LR\n subgraph \"Core Service Methods\"\n GU[get_user]\n SR[search_repositories]\n GAR[get_all_repositories]\n GB[get_branches]\n GST[get_suggested_tasks]\n end\n \n subgraph \"Repository Operations\"\n GRDFR[get_repository_details_from_repo_name]\n GPR[get_paginated_repos]\n SB[search_branches]\n GPB[get_paginated_branches]\n end\n \n subgraph \"Microagent Operations\"\n GM[get_microagents]\n GMC[get_microagent_content]\n end\n \n subgraph \"Pull Request Operations\"\n GPD[get_pr_details]\n IPO[is_pr_open]\n end\n \n GU --> User\n SR --> Repository\n GAR --> Repository\n GB --> Branch\n GST --> SuggestedTask\n GRDFR --> Repository\n GPR --> Repository\n SB --> Branch\n GPB --> PaginatedBranchesResponse\n GM --> MicroagentResponse\n GMC --> MicroagentContentResponse\n GPD --> dict\n IPO --> bool\n```\n\nSources: [openhands/integrations/service_types.py:437-542](), [openhands/integrations/service_types.py:116-151]()",
"Provider Implementation Details": "Each Git provider implements the service interface through a mixin-based architecture. For example, GitHub service combines multiple mixins:\n\n['`GitHubReposMixin`: Repository listing and search operations', '`GitHubBranchesMixin`: Branch management operations ', '`GitHubPRsMixin`: Pull request operations', '`GitHubFeaturesMixin`: Microagent and file operations', '`GitHubResolverMixin`: Issue resolution workflows']\n\nThe mixins inherit from `GitHubMixinBase`, which provides common HTTP client functionality and authentication handling.\n\nSources: [openhands/integrations/github/github_service.py:21-30](), [openhands/integrations/github/service/__init__.py:1-17](), [openhands/integrations/github/service/base.py:16-126]()"
},
"Authentication and Token Management": {
"Token Types and Configuration": "```\ngraph TB\n subgraph \"Token Management\"\n PT[ProviderToken]\n CS[CustomSecret]\n PTTM[PROVIDER_TOKEN_TYPE]\n CSTM[CUSTOM_SECRETS_TYPE]\n end\n \n subgraph \"Authentication Methods\"\n BT[Bearer Token]\n BA[Basic Auth]\n ET[External Token Manager]\n end\n \n subgraph \"Provider Environment Variables\"\n GT[GITHUB_TOKEN]\n GLT[GITLAB_TOKEN]\n BBT[BITBUCKET_TOKEN]\n end\n \n PT --> BT\n PT --> BA\n PT --> ET\n \n PTTM --> PT\n CSTM --> CS\n \n BT --> GT\n BT --> GLT\n BT --> BBT\n```\n\nThe `ProviderToken` class encapsulates authentication credentials with support for different token types and hosts. The system can automatically refresh tokens when they expire by detecting HTTP 401 responses.\n\nSources: [openhands/integrations/provider.py:41-68](), [openhands/integrations/provider.py:425-446]()"
},
"Evaluation System Integrations": {
"SWE-Bench Integration Architecture": "```\ngraph TB\n subgraph \"Evaluation Entry Points\"\n RI[run_infer.py]\n RII[run_infer_interact.py]\n EI[eval_infer.sh]\n RIS[run_infer.sh]\n end\n \n subgraph \"Core Evaluation Functions\"\n PI[process_instance]\n GC[get_config]\n IR[initialize_runtime]\n CR[complete_runtime]\n GI[get_instruction]\n end\n \n subgraph \"Dataset Support\"\n SB[SWE-bench]\n SBL[SWE-bench_Lite]\n SBV[SWE-bench_Verified]\n SBM[SWE-bench_Multimodal]\n SBLIVE[SWE-bench-Live]\n SWG[SWE-Gym]\n SWTB[SWT-Bench]\n end\n \n subgraph \"Evaluation Infrastructure\"\n DI[Docker Images]\n RT[Remote Runtime]\n EM[EvalMetadata]\n EO[EvalOutput]\n end\n \n RI --> PI\n RI --> GC\n RI --> IR\n RI --> CR\n RI --> GI\n \n PI --> EM\n PI --> EO\n \n GC --> DI\n GC --> RT\n \n RI --> SB\n RI --> SBL\n RI --> SBV\n RI --> SBM\n RI --> SBLIVE\n RI --> SWG\n RI --> SWTB\n```\n\nThe evaluation system processes individual benchmark instances through a standardized pipeline that includes runtime initialization, instruction generation, agent execution, and result collection.\n\nSources: [evaluation/benchmarks/swe_bench/run_infer.py:606-710](), [evaluation/utils/shared.py:164-216]()",
"Docker-based Evaluation Environment": "OpenHands uses instance-specific Docker images for SWE-Bench evaluation to ensure reproducible environments:\n\n```\ngraph LR\n subgraph \"Image Selection Logic\"\n IID[instance_id]\n GDI[get_instance_docker_image]\n SWBO[swebench_official_image]\n end\n \n subgraph \"Official Images\"\n SWEBI[swebench/sweb.eval.x86_64.*]\n SLI[starryzhang/*]\n SRI[swerebench/*]\n end\n \n subgraph \"OpenHands Images\"\n OHI[xingyaoww/sweb.eval.x86_64.*]\n GHCR[ghcr.io/openhands/*]\n end\n \n IID --> GDI\n GDI --> SWBO\n SWBO --> SWEBI\n SWBO --> SLI\n SWBO --> SRI\n GDI --> OHI\n GDI --> GHCR\n```\n\nThe system automatically selects appropriate Docker images based on the dataset type and instance ID, with support for both official SWE-Bench images and OpenHands-specific variants.\n\nSources: [evaluation/benchmarks/swe_bench/run_infer.py:178-204](), [evaluation/benchmarks/swe_bench/run_infer.py:210-232]()",
"Evaluation Modes and Dataset Support": "The evaluation system supports multiple modes and dataset variants:\n\n| Mode | Description | Template | Purpose |\n|------|-------------|----------|---------|\n| `swe` | Standard SWE-Bench evaluation | `swe_default.j2`, `swe_gpt4.j2` | Issue resolution |\n| `swt` | SWT-Bench test generation | `swt.j2` | Unit test creation |\n| `swt-ci` | SWT-Bench with CI setup | `swt.j2` + CI commands | Test generation with environment |\n\nThe instruction generation system uses Jinja2 templates to customize prompts based on the evaluation mode and model type.\n\nSources: [evaluation/benchmarks/swe_bench/run_infer.py:109-169](), [evaluation/benchmarks/swe_bench/run_infer.py:72-83]()"
},
"API Integration Points": {
"Server Routes for Git Operations": "OpenHands exposes Git provider functionality through REST API endpoints:\n\n```\ngraph TB\n subgraph \"API Routes (/api/user)\"\n GI[\"/installations\"]\n GR[\"/repositories\"] \n GUI[\"/info\"]\n SR[\"/search/repositories\"]\n SB[\"/search/branches\"]\n GST[\"/suggested-tasks\"]\n GRB[\"/repository/branches\"]\n GRM[\"/repository/{repo}/microagents\"]\n GRMC[\"/repository/{repo}/microagents/content\"]\n end\n \n subgraph \"Provider Operations\"\n GGHI[get_github_installations]\n GBWS[get_bitbucket_workspaces]\n GREP[get_repositories]\n GSREP[search_repositories]\n GSBR[search_branches]\n GSTASK[get_suggested_tasks]\n GBRANCH[get_branches]\n GMICRO[get_microagents]\n GMCONT[get_microagent_content]\n end\n \n GI --> GGHI\n GI --> GBWS\n GR --> GREP\n SR --> GSREP\n SB --> GSBR\n GST --> GSTASK\n GRB --> GBRANCH\n GRM --> GMICRO\n GRMC --> GMCONT\n```\n\nThe API routes handle authentication, provider selection, and error handling while delegating the actual operations to the `ProviderHandler`.\n\nSources: [openhands/server/routes/git.py:38-277](), [openhands/server/routes/git.py:292-421]()"
},
"Extension Points and Customization": {
"Adding New Git Providers": "The system allows for easy addition of new Git providers through the service interface:\n\n['Implement the `GitService` protocol', 'Create provider-specific mixins if needed', 'Register the service class in `ProviderHandler.service_class_map`', 'Add the provider to the `ProviderType` enum']\n\nThe HTTP client protocol provides a foundation for consistent error handling and authentication patterns across providers.\n\nSources: [openhands/integrations/provider.py:127-131](), [openhands/integrations/service_types.py:20-25](), [openhands/integrations/protocols/http_client.py:19-100]()",
"Custom Service Implementation": "Applications can override default service implementations by setting environment variables:\n\n['`OPENHANDS_GITHUB_SERVICE_CLS` for GitHub service customization', '`OPENHANDS_GITLAB_SERVICE_CLS` for GitLab service customization']\n\nThe `get_impl` utility dynamically loads the specified implementation class.\n\nSources: [openhands/integrations/github/github_service.py:74-78](), [openhands/integrations/gitlab/gitlab_service.py:78-82]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": [
{
"title": "Git Provider Integration",
"description": null,
"content": {
"Architecture Overview": {
"Provider Integration Architecture": "```\ngraph TB\n subgraph \"Client Layer\"\n API[\"/api/user routes<br/>git.py\"]\n WEB[\"Web Interface<br/>React Components\"]\n end\n \n subgraph \"Orchestration Layer\"\n PH[\"ProviderHandler<br/>provider.py\"]\n end\n \n subgraph \"Service Layer\"\n GS[\"GitService<br/>Protocol Interface\"]\n BGS[\"BaseGitService<br/>Abstract Base Class\"]\n end\n \n subgraph \"Provider Implementations\"\n GH[\"GitHubService<br/>github_service.py\"]\n GL[\"GitLabService<br/>gitlab_service.py\"]\n BB[\"BitBucketService<br/>bitbucket_service.py\"]\n end\n \n subgraph \"HTTP Layer\"\n HC[\"HTTPClient<br/>http_client.py\"]\n MIXINS[\"Provider Mixins<br/>Feature-specific classes\"]\n end\n \n API --> PH\n WEB --> API\n PH --> GH\n PH --> GL\n PH --> BB\n \n GH --> GS\n GL --> GS\n BB --> GS\n \n GS --> BGS\n BGS --> HC\n \n GH --> MIXINS\n GL --> MIXINS\n BB --> MIXINS\n \n style PH fill:#f9f9f9\n style GS fill:#e1f5fe\n style BGS fill:#e8f5e8\n```\n\n**Sources**: [openhands/integrations/provider.py:105-689](), [openhands/integrations/service_types.py:198-542](), [openhands/server/routes/git.py:35-421]()",
"Core Components Mapping": "```\ngraph LR\n subgraph \"Provider Types\"\n PT[\"ProviderType.GITHUB<br/>ProviderType.GITLAB<br/>ProviderType.BITBUCKET\"]\n end\n \n subgraph \"Service Classes\"\n GHS[\"GithubServiceImpl<br/>(get_impl pattern)\"]\n GLS[\"GitLabServiceImpl<br/>(get_impl pattern)\"]\n BBS[\"BitBucketServiceImpl<br/>(get_impl pattern)\"]\n end\n \n subgraph \"Token Management\"\n PTOKEN[\"ProviderToken<br/>.token, .user_id, .host\"]\n PTOKENS[\"PROVIDER_TOKEN_TYPE<br/>MappingProxyType\"]\n end\n \n subgraph \"Data Models\"\n REPO[\"Repository<br/>.full_name, .git_provider\"]\n USER[\"User<br/>.login, .avatar_url\"]\n BRANCH[\"Branch<br/>.name, .commit_sha\"]\n end\n \n PT --> GHS\n PT --> GLS\n PT --> BBS\n \n PTOKENS --> PTOKEN\n PTOKEN --> GHS\n PTOKEN --> GLS\n PTOKEN --> BBS\n \n GHS --> REPO\n GLS --> REPO\n BBS --> REPO\n \n GHS --> USER\n GLS --> USER\n BBS --> USER\n \n GHS --> BRANCH\n GLS --> BRANCH\n BBS --> BRANCH\n```\n\n**Sources**: [openhands/integrations/service_types.py:20-25](), [openhands/integrations/provider.py:41-68](), [openhands/integrations/provider.py:127-131]()"
},
"Provider Handler": {
"Core Functionality": "| Method | Purpose | Providers Supported |\n|--------|---------|-------------------|\n| `get_repositories()` | Fetch user repositories | All |\n| `search_repositories()` | Search public repositories | All |\n| `get_branches()` | Get repository branches | All |\n| `search_branches()` | Search branches within repository | All |\n| `get_microagents()` | Discover microagents | All |\n| `verify_repo_provider()` | Determine repository's provider | All |\n| `get_authenticated_git_url()` | Generate authenticated clone URLs | All |\n\nThe `ProviderHandler` maintains a service class mapping that dynamically instantiates provider services:\n\n```\nself.service_class_map: dict[ProviderType, type[GitService]] = {\n ProviderType.GITHUB: GithubServiceImpl,\n ProviderType.GITLAB: GitLabServiceImpl,\n ProviderType.BITBUCKET: BitBucketServiceImpl,\n}\n```\n\n**Sources**: [openhands/integrations/provider.py:105-161](), [openhands/integrations/provider.py:213-689]()"
},
"Service Implementation Architecture": {
"Mixin Structure": "```\ngraph TB\n subgraph \"GitHub Mixins\"\n GHBASE[\"GitHubMixinBase<br/>base.py\"]\n GHBRANCH[\"GitHubBranchesMixin<br/>branches_prs.py\"]\n GHFEATURE[\"GitHubFeaturesMixin<br/>features.py\"]\n GHPR[\"GitHubPRsMixin<br/>prs.py\"]\n GHREPO[\"GitHubReposMixin<br/>repos.py\"]\n GHRESOLVER[\"GitHubResolverMixin<br/>resolver.py\"]\n end\n \n subgraph \"GitLab Mixins\"\n GLBASE[\"GitLabMixinBase<br/>base.py\"]\n GLBRANCH[\"GitLabBranchesMixin<br/>branches.py\"]\n GLFEATURE[\"GitLabFeaturesMixin<br/>features.py\"]\n GLPR[\"GitLabPRsMixin<br/>prs.py\"]\n GLREPO[\"GitLabReposMixin<br/>repos.py\"]\n GLRESOLVER[\"GitLabResolverMixin<br/>resolver.py\"]\n end\n \n subgraph \"Final Services\"\n GHS[\"GitHubService<br/>Combines all mixins\"]\n GLS[\"GitLabService<br/>Combines all mixins\"]\n end\n \n GHBASE --> GHS\n GHBRANCH --> GHS\n GHFEATURE --> GHS\n GHPR --> GHS\n GHREPO --> GHS\n GHRESOLVER --> GHS\n \n GLBASE --> GLS\n GLBRANCH --> GLS\n GLFEATURE --> GLS\n GLPR --> GLS\n GLREPO --> GLS\n GLRESOLVER --> GLS\n```\n\n**Sources**: [openhands/integrations/github/service/__init__.py:1-17](), [openhands/integrations/gitlab/service/__init__.py:1-17](), [openhands/integrations/github/github_service.py:21-30](), [openhands/integrations/gitlab/gitlab_service.py:20-28]()",
"Base Implementation Pattern": "All provider mixins inherit from their respective base classes, which provide common HTTP client functionality:\n\n['**GitHubMixinBase**: Handles GitHub API authentication, headers, and GraphQL', '**GitLabMixinBase**: Manages GitLab API requests and GraphQL operations ', '**BitBucketMixinBase**: Provides Bitbucket API functionality with Basic/Bearer auth']\n\n**Sources**: [openhands/integrations/github/service/base.py:16-126](), [openhands/integrations/gitlab/service/base.py:15-178](), [openhands/integrations/bitbucket/service/base.py:19-248]()"
},
"Authentication and Token Management": {
"Token Types and Configuration": "```\ngraph LR\n subgraph \"Token Sources\"\n ENV[\"Environment Variables<br/>GITHUB_TOKEN<br/>GITLAB_TOKEN<br/>BITBUCKET_TOKEN\"]\n USER[\"User Secrets<br/>Web Interface\"]\n EXT[\"External Auth<br/>OAuth/SSO\"]\n end\n \n subgraph \"Token Processing\"\n PT[\"ProviderToken<br/>.token: SecretStr<br/>.user_id: str<br/>.host: str\"]\n PTM[\"PROVIDER_TOKEN_TYPE<br/>MappingProxyType\"]\n end\n \n subgraph \"Provider Auth\"\n GHAUTH[\"GitHub: Bearer token<br/>Enterprise: custom domain\"]\n GLAUTH[\"GitLab: Bearer token<br/>Self-hosted: custom URL\"]\n BBAUTH[\"Bitbucket: Basic/Bearer<br/>username:password support\"]\n end\n \n ENV --> PT\n USER --> PT\n EXT --> PT\n \n PT --> PTM\n PTM --> GHAUTH\n PTM --> GLAUTH\n PTM --> BBAUTH\n```\n\n**Sources**: [openhands/integrations/provider.py:41-68](), [openhands/integrations/provider.py:356-424](), [openhands/integrations/github/service/base.py:24-37](), [openhands/integrations/gitlab/service/base.py:23-35](), [openhands/integrations/bitbucket/service/base.py:51-66]()",
"Provider-Specific Authentication": "| Provider | Auth Method | Token Format | Custom Domains |\n|----------|-------------|--------------|----------------|\n| GitHub | Bearer | `ghp_xxx` or `gho_xxx` | GitHub Enterprise Server |\n| GitLab | Bearer | `glpat-xxx` | Self-hosted GitLab |\n| Bitbucket | Basic/Bearer | `username:password` or token | Bitbucket Server |\n\n**Sources**: [openhands/integrations/github/github_service.py:62-64](), [openhands/integrations/gitlab/gitlab_service.py:62-71](), [openhands/integrations/bitbucket/service/base.py:55-66]()"
},
"Core Operations": {
"Repository Management": "The system provides comprehensive repository operations across all providers:\n\n```\ngraph TB\n subgraph \"Repository Operations\"\n GETREPOS[\"get_all_repositories()<br/>User's repositories\"]\n SEARCHREPOS[\"search_repositories()<br/>Public repository search\"]\n GETDETAILS[\"get_repository_details_from_repo_name()<br/>Single repo details\"]\n VERIFY[\"verify_repo_provider()<br/>Determine provider\"]\n end\n \n subgraph \"Branch Operations\"\n GETBRANCHES[\"get_branches()<br/>List repository branches\"]\n PAGEBRANCHES[\"get_paginated_branches()<br/>Paginated branch listing\"]\n SEARCHBRANCHES[\"search_branches()<br/>Branch search within repo\"]\n end\n \n subgraph \"Microagent Operations\"\n GETMICRO[\"get_microagents()<br/>Discover microagents\"]\n GETCONTENT[\"get_microagent_content()<br/>Fetch microagent content\"]\n PARSECONTENT[\"_parse_microagent_content()<br/>Parse triggers\"]\n end\n \n GETREPOS --> Repository\n SEARCHREPOS --> Repository\n GETDETAILS --> Repository\n \n GETBRANCHES --> Branch\n PAGEBRANCHES --> PaginatedBranchesResponse\n SEARCHBRANCHES --> Branch\n \n GETMICRO --> MicroagentResponse\n GETCONTENT --> MicroagentContentResponse\n PARSECONTENT --> MicroagentContentResponse\n```\n\n**Sources**: [openhands/integrations/service_types.py:437-542](), [openhands/integrations/provider.py:213-689]()",
"Microagent Discovery": "OpenHands implements a sophisticated microagent discovery system that works across all Git providers:\n\n| Location | File Types | Purpose |\n|----------|------------|---------|\n| `.cursorrules` | Single file | Cursor IDE integration |\n| `.openhands/microagents/` | `*.md` files | OpenHands microagents |\n| `microagents/` | `*.md` files | Special repositories (.openhands, openhands-config) |\n\nThe discovery process follows a standardized pattern implemented in `BaseGitService`:\n\n['Check for `.cursorrules` file in repository root', 'Determine microagents directory path based on repository name', 'Scan directory for `.md` files (excluding `README.md`)', 'Parse microagent content and extract triggers']\n\n**Sources**: [openhands/integrations/service_types.py:244-421](), [openhands/integrations/provider.py:515-612]()"
},
"API Integration": {
"API Routes": "| Endpoint | Method | Purpose | Response Type |\n|----------|--------|---------|---------------|\n| `/api/user/repositories` | GET | List user repositories | `list[Repository]` |\n| `/api/user/search/repositories` | GET | Search repositories | `list[Repository]` |\n| `/api/user/repository/branches` | GET | Get repository branches | `PaginatedBranchesResponse` |\n| `/api/user/search/branches` | GET | Search branches | `list[Branch]` |\n| `/api/user/repository/{repo}/microagents` | GET | List microagents | `list[MicroagentResponse]` |\n| `/api/user/repository/{repo}/microagents/content` | GET | Get microagent content | `MicroagentContentResponse` |\n| `/api/user/installations` | GET | List installations | `list[str]` |\n| `/api/user/suggested-tasks` | GET | Get suggested tasks | `list[SuggestedTask]` |\n\n**Sources**: [openhands/server/routes/git.py:35-421]()",
"Request Flow": "```\nsequenceDiagram\n participant Client\n participant API as \"git.py routes\"\n participant PH as \"ProviderHandler\"\n participant Service as \"Provider Service\"\n participant Provider as \"Git Provider API\"\n \n Client->>API: GET /api/user/repositories\n API->>PH: get_repositories()\n PH->>Service: get_all_repositories()\n Service->>Provider: HTTP requests\n Provider-->>Service: Repository data\n Service-->>PH: list[Repository]\n PH-->>API: list[Repository]\n API-->>Client: JSON response\n```\n\n**Sources**: [openhands/server/routes/git.py:65-102](), [openhands/integrations/provider.py:213-245]()"
},
"Extension Points": {
"Custom Service Implementation": "Applications can substitute custom provider implementations using environment variables:\n\n['`OPENHANDS_GITHUB_SERVICE_CLS`: Custom GitHub service class', '`OPENHANDS_GITLAB_SERVICE_CLS`: Custom GitLab service class']\n\nThe implementations are loaded dynamically using the `get_impl()` pattern from `openhands.utils.import_utils`.\n\n**Sources**: [openhands/integrations/github/github_service.py:74-78](), [openhands/integrations/gitlab/gitlab_service.py:78-82]()",
"Protocol-Based Design": "The `GitService` protocol defines the interface contract that all providers must implement, enabling new provider additions without modifying existing code:\n\n```\nclass GitService(Protocol):\n async def get_user(self) -> User: ...\n async def search_repositories(self, query: str, per_page: int, sort: str, order: str, public: bool) -> list[Repository]: ...\n async def get_all_repositories(self, sort: str, app_mode: AppMode) -> list[Repository]: ...\n # ... additional methods\n```\n\n**Sources**: [openhands/integrations/service_types.py:437-542]()",
"Mixin Architecture": "The mixin-based design allows feature-specific customization by overriding individual mixin classes while inheriting common functionality from base classes.\n\n**Sources**: [openhands/integrations/github/github_service.py:31-42](), [openhands/integrations/gitlab/gitlab_service.py:29-39]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
},
{
"title": "Evaluation & Benchmarking",
"description": null,
"content": {
"Core Evaluation Framework": {
"Evaluation Data Models": "The framework uses two primary data models to structure evaluation workflows:\n\n```\ngraph TD\n subgraph \"Evaluation Data Models\"\n EM[\"EvalMetadata<br/>Configuration & Setup\"]\n EO[\"EvalOutput<br/>Results & Metrics\"]\n end\n \n subgraph \"EvalMetadata Components\"\n AC[\"agent_class: str\"]\n LC[\"llm_config: LLMConfig\"]\n MI[\"max_iterations: int\"]\n EOD[\"eval_output_dir: str\"]\n DS[\"dataset: str\"]\n CC[\"condenser_config: CondenserConfig\"]\n end\n \n subgraph \"EvalOutput Components\"\n IID[\"instance_id: str\"]\n TR[\"test_result: dict\"]\n HIS[\"history: list[dict]\"]\n MET[\"metrics: dict\"]\n ERR[\"error: str | None\"]\n end\n \n EM --> AC\n EM --> LC\n EM --> MI\n EM --> EOD\n EM --> DS\n EM --> CC\n \n EO --> IID\n EO --> TR\n EO --> HIS\n EO --> MET\n EO --> ERR\n```\n\n**Sources:** [evaluation/utils/shared.py:44-79]()",
"Evaluation Orchestration": "The core evaluation process is managed by the `run_evaluation` function, which handles parallelization, error recovery, and progress tracking:\n\n```\ngraph LR\n subgraph \"Dataset Preparation\"\n DD[\"Dataset DataFrame\"]\n PD[\"prepare_dataset()\"]\n FD[\"Filtered Dataset\"]\n end\n \n subgraph \"Evaluation Execution\" \n RE[\"run_evaluation()\"]\n PIW[\"_process_instance_wrapper()\"]\n PIF[\"process_instance_func()\"]\n end\n \n subgraph \"Output Processing\"\n UP[\"update_progress()\"]\n OF[\"output.jsonl\"]\n MR[\"Metrics & Reports\"]\n end\n \n DD --> PD\n PD --> FD\n FD --> RE\n RE --> PIW\n PIW --> PIF\n PIF --> UP\n UP --> OF\n UP --> MR\n \n PIW --> PIW\n```\n\n**Sources:** [evaluation/utils/shared.py:486-550](), [evaluation/utils/shared.py:219-289]()"
},
"SWE-Bench Integration": {
"Benchmark Variants Support": "The evaluation system supports multiple SWE-Bench dataset variants through dynamic configuration:\n\n```\ngraph TD\n subgraph \"Dataset Type Detection\"\n SDT[\"set_dataset_type()\"]\n DN[\"Dataset Name Analysis\"]\n end\n \n subgraph \"Supported Variants\"\n SB[\"SWE-bench<br/>Standard\"]\n SBL[\"SWE-bench-Live<br/>Real Issues\"]\n SBR[\"SWE-rebench<br/>Extended\"]\n SG[\"SWE-Gym<br/>Interactive\"]\n MM[\"Multimodal<br/>Visual Tasks\"]\n end\n \n subgraph \"Image Selection\"\n GID[\"get_instance_docker_image()\"]\n OFF[\"Official Images\"]\n OH[\"OpenHands Images\"]\n end\n \n SDT --> DN\n DN --> SB\n DN --> SBL \n DN --> SBR\n DN --> SG\n DN --> MM\n \n SB --> GID\n SBL --> GID\n SBR --> GID\n SG --> GID\n MM --> GID\n \n GID --> OFF\n GID --> OH\n```\n\n**Sources:** [evaluation/benchmarks/swe_bench/run_infer.py:78-95](), [evaluation/benchmarks/swe_bench/run_infer.py:178-204]()",
"Instance Processing Workflow": "Each evaluation instance follows a standardized processing workflow that includes runtime initialization, agent execution, and results collection:\n\n```\ngraph TD\n subgraph \"Instance Setup\"\n GC[\"get_config()\"]\n CR[\"create_runtime()\"]\n IR[\"initialize_runtime()\"]\n end\n \n subgraph \"Agent Execution\"\n GI[\"get_instruction()\"]\n RC[\"run_controller()\"]\n MA[\"MessageAction\"]\n end\n \n subgraph \"Results Collection\"\n CR2[\"complete_runtime()\"]\n GP[\"Generate Git Patch\"]\n GM[\"get_metrics()\"]\n EO[\"EvalOutput Creation\"]\n end\n \n GC --> CR\n CR --> IR\n IR --> GI\n GI --> MA\n MA --> RC\n RC --> CR2\n CR2 --> GP\n GP --> GM\n GM --> EO\n```\n\n**Sources:** [evaluation/benchmarks/swe_bench/run_infer.py:606-710](), [evaluation/benchmarks/swe_bench/run_infer.py:267-435]()"
},
"Evaluation Modes and Variants": {
"Standard vs Interactive Evaluation": "The system provides both standard autonomous evaluation and interactive evaluation where agents can communicate with simulated users:\n\n```\ngraph LR\n subgraph \"Standard Mode\"\n SM[\"Standard Evaluation\"]\n AP[\"Autonomous Processing\"] \n SP[\"Single-shot Problem Solving\"]\n end\n \n subgraph \"Interactive Mode\"\n IM[\"Interactive Evaluation\"]\n FU[\"FakeUser Simulation\"]\n QA[\"Question-Answer Cycles\"]\n end\n \n subgraph \"Shared Components\"\n PI[\"process_instance()\"]\n CR[\"complete_runtime()\"]\n RES[\"Results Collection\"]\n end\n \n SM --> AP\n AP --> SP\n SP --> PI\n \n IM --> FU\n FU --> QA\n QA --> PI\n \n PI --> CR\n CR --> RES\n```\n\n**Sources:** [evaluation/benchmarks/swe_bench/run_infer_interact.py:48-91](), [evaluation/benchmarks/swe_bench/run_infer_interact.py:97-104]()",
"SWT-Bench Test Generation Mode": "For test generation evaluation, the system modifies prompts and setup to focus on creating unit tests rather than fixing issues:\n\n| Mode | Purpose | Environment Setup | Prompt Template |\n|------|---------|-------------------|-----------------|\n| `swe` | Issue Resolution | Standard | `swe_default.j2` |\n| `swt` | Test Generation | Standard | `swt.j2` |\n| `swt-ci` | Test Gen + CI | Pre-install deps | `swt.j2` + test commands |\n\n**Sources:** [evaluation/benchmarks/swe_bench/run_infer.py:109-151](), [evaluation/benchmarks/swe_bench/run_infer.py:395-418]()"
},
"Configuration and Customization": {
"Environment Configuration": "Key environment variables control evaluation behavior:\n\n```\ngraph TD\n subgraph \"Core Settings\"\n RT[\"RUNTIME<br/>docker|remote\"]\n IEM[\"ITERATIVE_EVAL_MODE<br/>true|false\"]\n WB[\"RUN_WITH_BROWSING<br/>true|false\"]\n end\n \n subgraph \"Memory Management\"\n EC[\"EVAL_CONDENSER<br/>Config Name\"]\n CC[\"CondenserConfig<br/>Memory Optimization\"]\n end\n \n subgraph \"Error Handling\" \n ESME[\"EVAL_SKIP_MAXIMUM_RETRIES_EXCEEDED<br/>true|false\"]\n MRE[\"maximum_retries_exceeded.jsonl<br/>Failed Instances Log\"]\n end\n \n subgraph \"Remote Runtime\"\n AAK[\"ALLHANDS_API_KEY\"]\n SRA[\"SANDBOX_REMOTE_RUNTIME_API_URL\"]\n EDP[\"EVAL_DOCKER_IMAGE_PREFIX\"]\n end\n \n RT --> CC\n IEM --> ESME\n WB --> EC\n EC --> CC\n ESME --> MRE\n \n AAK --> SRA\n SRA --> EDP\n```\n\n**Sources:** [evaluation/benchmarks/swe_bench/run_infer.py:69-71](), [evaluation/utils/shared.py:440-453]()",
"Instance Filtering and Selection": "Evaluations can be customized through TOML configuration files to run on specific subsets:\n\n```\ngraph TD\n subgraph \"Selection Methods\"\n CT[\"config.toml\"]\n SI[\"selected_ids<br/>Specific Instances\"]\n SR[\"selected_repos<br/>Repository Filter\"]\n SK[\"SKIP_IDS<br/>Environment Variable\"]\n end\n \n subgraph \"Dataset Processing\"\n FD[\"filter_dataset()\"]\n PD[\"prepare_dataset()\"]\n RD[\"Reduced Dataset\"]\n end\n \n CT --> SI\n CT --> SR\n SK --> FD\n SI --> FD\n SR --> FD\n FD --> PD\n PD --> RD\n```\n\n**Sources:** [evaluation/benchmarks/swe_bench/run_infer.py:713-744](), [evaluation/utils/shared.py:219-289]()"
},
"Results Processing and Metrics": {
"Metrics Collection": "Multiple metric sources are combined to provide comprehensive evaluation data:\n\n```\ngraph TD\n subgraph \"Metrics Sources\"\n CS[\"ConversationStats<br/>Primary Source\"] \n SM[\"state.metrics<br/>Legacy Fallback\"]\n CM[\"Condensation Metadata<br/>Memory Usage\"]\n end\n \n subgraph \"Metrics Processing\"\n GM[\"get_metrics()\"]\n CMB[\"Combined Metrics\"]\n GCM[\"get_condensation_metadata()\"]\n end\n \n subgraph \"Output Formats\"\n EO[\"EvalOutput.metrics\"]\n JSON[\"output.jsonl\"]\n REP[\"report.json\"]\n end\n \n CS --> GM\n SM --> GM\n GM --> CMB\n CMB --> GCM\n GCM --> CM\n \n GM --> EO\n EO --> JSON\n JSON --> REP\n```\n\n**Sources:** [evaluation/utils/shared.py:670-689](), [evaluation/utils/shared.py:59-79]()",
"Output Structure and Formats": "Evaluation results are structured consistently across all benchmark types:\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `instance_id` | string | Unique identifier for the task |\n| `instruction` | string | Original problem statement |\n| `test_result` | object | Benchmark-specific results (e.g., git_patch) |\n| `history` | array | Complete interaction history |\n| `metrics` | object | Performance and usage metrics |\n| `error` | string | Error message if evaluation failed |\n| `metadata` | object | Configuration and environment details |\n\n**Sources:** [evaluation/utils/shared.py:59-79]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
}
]
},
{
"title": "Development & Contributing",
"description": null,
"content": {
"Development Setup": {
"Build System Architecture": "```\ngraph TD\n DEV[\"Developer\"]\n MAKE[\"Makefile\"]\n \n subgraph \"Dependency Management\"\n CHECK[\"check-dependencies\"]\n POETRY[\"install-python-dependencies\"]\n NPM[\"install-frontend-dependencies\"]\n PRECOMMIT[\"install-pre-commit-hooks\"]\n end\n \n subgraph \"Build Process\"\n FRONTEND[\"build-frontend\"]\n BACKEND[\"Backend (Poetry)\"]\n ASSETS[\"Static Assets\"]\n end\n \n subgraph \"Quality Control\"\n LINT_PY[\"lint-backend\"]\n LINT_FE[\"lint-frontend\"]\n TEST[\"test-frontend\"]\n HOOKS[\"pre-commit hooks\"]\n end\n \n DEV --> MAKE\n MAKE --> CHECK\n CHECK --> POETRY\n CHECK --> NPM\n CHECK --> PRECOMMIT\n \n POETRY --> BACKEND\n NPM --> FRONTEND\n FRONTEND --> ASSETS\n \n MAKE --> LINT_PY\n MAKE --> LINT_FE\n MAKE --> TEST\n PRECOMMIT --> HOOKS\n\n POETRY --> HOOKS\n NPM --> HOOKS\n```\n\nThe build system coordinates several key components:\n\n['**`make build`** - Main build target that orchestrates all setup steps', '**`check-dependencies`** - Validates system requirements (Python 3.12, Node.js 22, Docker, Poetry, tmux)', '**`install-python-dependencies`** - Uses Poetry to install Python packages with optional Playwright support', '**`install-frontend-dependencies`** - Uses npm to install Node.js dependencies', '**`build-frontend`** - Compiles React application with Vite']\n\nSources: [Makefile:25-32](), [Makefile:34-45](), [Makefile:139-175](), [Makefile:177-183](), [Makefile:244-246]()",
"Development Dependencies": "The project requires specific versions of core tools:\n\n| Tool | Required Version | Purpose |\n|------|-----------------|---------|\n| Python | 3.12 | Backend runtime and package management |\n| Node.js | 22.x+ | Frontend build and runtime |\n| Poetry | 1.8+ | Python dependency management |\n| Docker | Latest | Container runtime for sandboxed execution |\n| tmux | Optional | Advanced terminal features |\n\nThe dependency checking system validates these requirements and provides installation guidance when tools are missing.\n\nSources: [Makefile:14](), [Makefile:64-96](), [Makefile:119-137]()"
},
"Code Quality & Linting": {
"Linting Architecture": "```\ngraph TD\n subgraph \"Frontend Linting\"\n ESLINT[\"ESLint Config\"]\n TS[\"TypeScript\"]\n PRETTIER[\"Prettier\"]\n I18N[\"i18next checks\"]\n end\n \n subgraph \"Backend Linting\"\n PRECOMMIT[\"pre-commit-config.yaml\"]\n BLACK[\"Black formatter\"]\n ISORT[\"isort import sorting\"]\n FLAKE8[\"Flake8 linting\"]\n MYPY[\"MyPy type checking\"]\n end\n \n subgraph \"Git Integration\"\n HUSKY[\"Husky pre-commit\"]\n STAGED[\"lint-staged\"]\n HOOKS[\"Git hooks\"]\n end\n \n MAKE_LINT[\"make lint\"] --> ESLINT\n MAKE_LINT --> PRECOMMIT\n \n ESLINT --> TS\n ESLINT --> PRETTIER\n ESLINT --> I18N\n \n PRECOMMIT --> BLACK\n PRECOMMIT --> ISORT\n PRECOMMIT --> FLAKE8\n PRECOMMIT --> MYPY\n \n HUSKY --> STAGED\n STAGED --> ESLINT\n HUSKY --> PRECOMMIT\n HOOKS --> HUSKY\n```\n\nThe linting system uses different tools for frontend and backend code:\n\n**Frontend linting** (`npm run lint`):\n\n['ESLint with Airbnb config and TypeScript support', 'Prettier for code formatting', 'i18next plugin for internationalization string checking', 'TypeScript compilation verification']\n\n**Backend linting** (`pre-commit`):\n\n['Black for Python code formatting', 'isort for import statement organization', 'Flake8 for style guide enforcement', 'MyPy for static type checking']\n\nSources: [frontend/.eslintrc:1-76](), [frontend/.husky/pre-commit:1-10](), [Makefile:191-201]()",
"Pre-commit Hook Integration": "The project uses Husky and lint-staged for Git integration:\n\n['**Husky** manages Git hooks and triggers checks on commit', '**lint-staged** runs linters only on staged files', '**Pre-commit framework** handles Python-side linting with configuration in `dev_config/python/.pre-commit-config.yaml`']\n\nThis ensures code quality standards are enforced before commits reach the repository.\n\nSources: [frontend/.husky/pre-commit:1-10](), [Makefile:185-189]()"
},
"CI/CD Pipeline": {
"GitHub Actions Workflow Architecture": "```\ngraph TD\n subgraph \"Trigger Events\"\n PR[\"Pull Request\"]\n PUSH_MAIN[\"Push to main\"]\n TAG[\"Tag creation\"]\n MANUAL[\"Manual dispatch\"]\n end\n \n subgraph \"Core Workflows\"\n LINT_WF[\"lint.yml\"]\n BUILD_WF[\"ghcr-build.yml\"]\n FE_TEST[\"fe-unit-tests.yml\"]\n end\n \n subgraph \"Build Jobs\"\n DEFINE[\"define-matrix\"]\n BUILD_APP[\"ghcr_build_app\"]\n BUILD_RT[\"ghcr_build_runtime\"]\n BUILD_ENT[\"ghcr_build_enterprise\"]\n end\n \n subgraph \"Test Jobs\"\n TEST_RT_ROOT[\"test_runtime_root\"]\n TEST_RT_OH[\"test_runtime_oh\"]\n FE_TESTS[\"Frontend tests\"]\n end\n \n subgraph \"Registry\"\n GHCR[\"GitHub Container Registry\"]\n IMAGES[\"Docker images\"]\n end\n \n PR --> LINT_WF\n PR --> BUILD_WF\n PR --> FE_TEST\n PUSH_MAIN --> BUILD_WF\n TAG --> BUILD_WF\n MANUAL --> BUILD_WF\n \n BUILD_WF --> DEFINE\n DEFINE --> BUILD_APP\n DEFINE --> BUILD_RT\n BUILD_RT --> BUILD_ENT\n \n BUILD_RT --> TEST_RT_ROOT\n BUILD_RT --> TEST_RT_OH\n \n BUILD_APP --> GHCR\n BUILD_RT --> GHCR\n BUILD_ENT --> GHCR\n GHCR --> IMAGES\n \n FE_TEST --> FE_TESTS\n LINT_WF --> FE_TESTS\n```\n\nThe CI/CD system is built around GitHub Actions with several key workflows:\n\n**Primary Build Workflow** (`ghcr-build.yml`):\n\n['Builds application, runtime, and enterprise Docker images', 'Supports multi-platform builds (linux/amd64, linux/arm64)', 'Pushes to GitHub Container Registry (GHCR)', 'Runs comprehensive runtime testing']\n\n**Quality Assurance** (`lint.yml`):\n\n['Frontend linting with ESLint and TypeScript compilation', 'Backend linting with pre-commit hooks', 'Translation completeness checking', 'Version consistency validation']\n\n**Testing** (`fe-unit-tests.yml`):\n\n['Frontend unit tests with coverage reporting', 'TypeScript compilation verification']\n\nSources: [.github/workflows/ghcr-build.yml:1-421](), [.github/workflows/lint.yml:1-88](), [.github/workflows/fe-unit-tests.yml:1-45]()",
"Build Matrix Strategy": "The CI system uses a dynamic build matrix to optimize build times:\n\n```\ngraph LR\n subgraph \"Base Images\"\n NIKOLAIK[\"nikolaik/python-nodejs:python3.12-nodejs22\"]\n UBUNTU[\"ubuntu:24.04\"]\n end\n \n subgraph \"Build Variants\"\n PR_BUILD[\"PR builds (nikolaik only)\"]\n FULL_BUILD[\"Full builds (both images)\"]\n end\n \n subgraph \"Outputs\"\n RUNTIME_NIKOLAIK[\"runtime:*-nikolaik\"]\n RUNTIME_UBUNTU[\"runtime:*-ubuntu\"]\n APP[\"openhands:*\"]\n ENTERPRISE[\"enterprise-server:*\"]\n end\n \n NIKOLAIK --> PR_BUILD\n NIKOLAIK --> FULL_BUILD\n UBUNTU --> FULL_BUILD\n \n PR_BUILD --> RUNTIME_NIKOLAIK\n FULL_BUILD --> RUNTIME_NIKOLAIK\n FULL_BUILD --> RUNTIME_UBUNTU\n \n RUNTIME_NIKOLAIK --> APP\n RUNTIME_UBUNTU --> ENTERPRISE\n```\n\n['**Pull Requests**: Build only nikolaik variant to save CI resources', '**Main/Tag builds**: Build both nikolaik and ubuntu variants for full platform support', '**Conditional execution**: Fork repositories cannot push to GHCR but still build for validation']\n\nSources: [.github/workflows/ghcr-build.yml:31-52](), [.github/workflows/ghcr-build.yml:96-99]()"
},
"Docker Build System": {
"Runtime Image Build Process": "```\ngraph TD\n subgraph \"Build Orchestration\"\n RUNTIME_BUILD[\"runtime_build.py\"]\n BUILDER_FACTORY[\"RuntimeBuilder Factory\"]\n BUILD_FOLDER[\"Build Context Preparation\"]\n end\n \n subgraph \"Docker Builders\"\n DOCKER_BUILDER[\"DockerRuntimeBuilder\"]\n REMOTE_BUILDER[\"RemoteRuntimeBuilder\"]\n BUILDX[\"Docker Buildx\"]\n end\n \n subgraph \"Image Optimization\"\n HASH_CALC[\"Hash Calculation\"]\n CACHE_LOOKUP[\"Cache Layer Lookup\"]\n TAG_STRATEGY[\"Multi-tier Tagging\"]\n end\n \n subgraph \"Build Artifacts\"\n SOURCE_FILES[\"Source Code\"]\n DOCKERFILE[\"Generated Dockerfile.j2\"]\n POETRY_LOCK[\"poetry.lock\"]\n PYPROJECT[\"pyproject.toml\"]\n end\n \n RUNTIME_BUILD --> BUILDER_FACTORY\n BUILDER_FACTORY --> DOCKER_BUILDER\n BUILDER_FACTORY --> REMOTE_BUILDER\n \n RUNTIME_BUILD --> BUILD_FOLDER\n BUILD_FOLDER --> SOURCE_FILES\n BUILD_FOLDER --> DOCKERFILE\n BUILD_FOLDER --> POETRY_LOCK\n BUILD_FOLDER --> PYPROJECT\n \n RUNTIME_BUILD --> HASH_CALC\n HASH_CALC --> CACHE_LOOKUP\n CACHE_LOOKUP --> TAG_STRATEGY\n \n DOCKER_BUILDER --> BUILDX\n TAG_STRATEGY --> BUILDX\n```\n\nThe Docker build system implements sophisticated caching and optimization:\n\n**Build Strategy Hierarchy**:\n\n['**SCRATCH**: Build from base image with no reused layers', '**VERSIONED**: Reuse image with same base + OpenHands version ', '**LOCK**: Reuse image with identical dependency locks (fastest)']\n\n**Hash-based Tagging**:\n\n['`get_hash_for_lock_files()`: Creates hash from `pyproject.toml` and `poetry.lock`', '`get_hash_for_source_files()`: Creates hash from source code changes', '`get_tag_for_versioned_image()`: Creates tag from base image identifier']\n\n**Multi-tier Image Tags**:\n\n['Source tag: `oh_v{version}_{lock_hash}_{source_hash}`', 'Lock tag: `oh_v{version}_{lock_hash}`', 'Versioned tag: `oh_v{version}_{base_image_tag}`']\n\nSources: [openhands/runtime/utils/runtime_build.py:108-255](), [openhands/runtime/utils/runtime_build.py:320-358](), [openhands/runtime/builder/docker.py:51-249]()",
"Container Build Script Architecture": "```\ngraph TD\n subgraph \"Build Script (build.sh)\"\n ARGS[\"Argument Parsing\"]\n CONFIG[\"config.sh Loading\"]\n TAG_GEN[\"Tag Generation\"]\n BUILDX_CMD[\"Buildx Command Assembly\"]\n end\n \n subgraph \"Configuration Sources\"\n ENV_VARS[\"Environment Variables\"]\n GIT_INFO[\"Git Information\"]\n VERSION_INFO[\"Version Information\"]\n end\n \n subgraph \"Build Targets\"\n APP_BUILD[\"openhands app\"]\n RUNTIME_BUILD[\"runtime images\"]\n CUSTOM_BUILD[\"custom containers\"]\n end\n \n subgraph \"Registry Operations\"\n CACHE_PULL[\"Cache Pull\"]\n IMAGE_PUSH[\"Image Push\"]\n TAG_APPLY[\"Tag Application\"]\n end\n \n ARGS --> CONFIG\n CONFIG --> TAG_GEN\n \n ENV_VARS --> TAG_GEN\n GIT_INFO --> TAG_GEN\n VERSION_INFO --> TAG_GEN\n \n TAG_GEN --> BUILDX_CMD\n BUILDX_CMD --> APP_BUILD\n BUILDX_CMD --> RUNTIME_BUILD\n BUILDX_CMD --> CUSTOM_BUILD\n \n BUILDX_CMD --> CACHE_PULL\n BUILDX_CMD --> IMAGE_PUSH\n BUILDX_CMD --> TAG_APPLY\n```\n\nThe `containers/build.sh` script serves as a universal Docker build orchestrator:\n\n**Key Parameters**:\n\n['`-i <image_name>`: Target image (openhands, runtime, etc.)', '`-o <org_name>`: Docker organization/registry prefix', '`--push`: Push to registry after build', '`--load`: Load image locally after build', '`-t <tag_suffix>`: Additional tag suffix', '`--dry`: Generate build configuration without building']\n\n**Tag Generation Logic**:\n\n['Git commit SHA for tracking builds', 'Branch/tag names for version identification', 'Semantic version parsing for release builds', 'Cache optimization tags for build acceleration']\n\nSources: [containers/build.sh:1-183](), [containers/build.sh:45-78](), [containers/build.sh:118-176]()"
},
"Development Workflows": {
"Local Development Setup": "```\ngraph TD\n subgraph \"Initial Setup\"\n CLONE[\"git clone\"]\n DEPS[\"make build\"]\n CONFIG[\"make setup-config\"]\n end\n \n subgraph \"Development Mode\"\n RUN[\"make run\"]\n BACKEND[\"Backend (FastAPI)\"]\n FRONTEND[\"Frontend (Vite)\"]\n WORKSPACE[\"Workspace Mount\"]\n end\n \n subgraph \"Code Quality\"\n LINT_LOCAL[\"make lint\"]\n PRE_COMMIT[\"pre-commit hooks\"]\n TESTS[\"make test\"]\n end\n \n subgraph \"Container Development\"\n DOCKER_RUN[\"make docker-run\"]\n DOCKER_DEV[\"make docker-dev\"]\n CONTAINERS[\"Docker Compose\"]\n end\n \n CLONE --> DEPS\n DEPS --> CONFIG\n CONFIG --> RUN\n \n RUN --> BACKEND\n RUN --> FRONTEND\n RUN --> WORKSPACE\n \n LINT_LOCAL --> PRE_COMMIT\n PRE_COMMIT --> TESTS\n \n DOCKER_RUN --> CONTAINERS\n DOCKER_DEV --> CONTAINERS\n```\n\n**Standard Development Flow**:\n\n['**Environment Setup**: `make build` handles all dependency installation and pre-commit hook setup', '**Configuration**: `make setup-config` creates initial `config.toml` with LLM settings and workspace path', '**Local Development**: `make run` starts both backend (port 3000) and frontend (port 3001) servers', '**Docker Development**: `make docker-run` or `make docker-dev` for containerized development']\n\n**Development Server Architecture**:\n\n['**Backend**: FastAPI server with hot reload via `uvicorn --reload`', '**Frontend**: Vite development server with HMR (Hot Module Replacement)', '**Workspace**: Configurable workspace directory for agent file operations']\n\nSources: [Makefile:279-283](), [Makefile:249-263](), [Makefile:286-297](), [Makefile:301-333]()",
"Contributing Process": "The contribution workflow enforces code quality through automated checks:\n\n**Pre-commit Validation**:\n\n['Frontend linting (ESLint, Prettier, TypeScript)', 'Backend linting (Black, isort, flake8, MyPy) ', 'Translation completeness verification', 'Import organization and unused import removal']\n\n**CI Pipeline Integration**:\n\n['All PRs trigger lint and build workflows', 'Runtime tests execute against built Docker images', 'Fork repositories build locally but cannot push to registry', 'Auto-fix workflows available via `lint-fix` label']\n\n**Quality Gates**:\n\n['Pre-commit hooks prevent commits with linting issues', 'CI workflows must pass before merge', 'Docker builds verify runtime compatibility', 'Translation coverage ensures internationalization completeness']\n\nSources: [.github/workflows/lint-fix.yml:1-98](), [frontend/.husky/pre-commit:1-10](), [frontend/scripts/check-translation-completeness.cjs:1-89]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": [
{
"title": "Build System & Dependencies",
"description": null,
"content": {
"Overview": {
"Build System Architecture": "```\ngraph TB\n subgraph \"Build Orchestration\"\n MAKE[\"Makefile<br/>Primary Build Interface\"]\n SCRIPTS[\"Build Scripts<br/>containers/build.sh\"]\n end\n \n subgraph \"Python Backend\"\n POETRY[\"Poetry<br/>pyproject.toml\"]\n LOCK_PY[\"poetry.lock<br/>Dependency Lock\"]\n GROUPS[\"Dependency Groups<br/>main, dev, test, runtime, evaluation\"]\n end\n \n subgraph \"Frontend\"\n NPM[\"npm<br/>package.json\"]\n LOCK_JS[\"package-lock.json<br/>Dependency Lock\"]\n SCRIPTS_JS[\"Build Scripts<br/>dev, build, test\"]\n end\n \n subgraph \"Containerization\"\n DOCKERFILE_APP[\"containers/app/Dockerfile<br/>Application Container\"]\n DOCKERFILE_RUNTIME[\"containers/runtime/Dockerfile<br/>Runtime Container\"]\n COMPOSE_DEV[\"containers/dev/compose.yml<br/>Development\"]\n COMPOSE_PROD[\"docker-compose.yml<br/>Production\"]\n end\n \n subgraph \"CI/CD\"\n GH_ACTIONS[\"GitHub Actions<br/>Automated Workflows\"]\n LINT[\".github/workflows/lint.yml\"]\n BUILD_WORKFLOWS[\"Build & Test Workflows\"]\n end\n \n MAKE --> POETRY\n MAKE --> NPM\n MAKE --> DOCKERFILE_APP\n MAKE --> DOCKERFILE_RUNTIME\n \n POETRY --> LOCK_PY\n NPM --> LOCK_JS\n \n SCRIPTS --> DOCKERFILE_APP\n SCRIPTS --> DOCKERFILE_RUNTIME\n \n GH_ACTIONS --> MAKE\n GH_ACTIONS --> POETRY\n GH_ACTIONS --> NPM\n```\n\nSources: [Makefile:1-372](), [pyproject.toml:1-199](), [frontend/package.json:1-152](), [containers/build.sh:1-183]()"
},
"Python Dependency Management": {
"Poetry Configuration Structure": "```\ngraph TB\n subgraph \"pyproject.toml Structure\"\n BUILD_SYSTEM[\"build-system<br/>poetry-core.masonry.api\"]\n TOOL_POETRY[\"tool.poetry<br/>Project Metadata\"]\n DEPENDENCIES[\"tool.poetry.dependencies<br/>Runtime Dependencies\"]\n GROUPS[\"tool.poetry.group.*<br/>Dependency Groups\"]\n EXTRAS[\"tool.poetry.extras<br/>Optional Features\"]\n SCRIPTS[\"tool.poetry.scripts<br/>CLI Entrypoints\"]\n end\n \n subgraph \"Dependency Groups\"\n DEV[\"dev<br/>Development Tools\"]\n TEST[\"test<br/>Testing Framework\"]\n RUNTIME[\"runtime<br/>Jupyter/Notebook\"]\n EVALUATION[\"evaluation<br/>Benchmarking\"]\n TESTGENEVAL[\"testgeneval<br/>Test Generation\"]\n end\n \n subgraph \"Core Dependencies\"\n LITELLM[\"litellm ^1.74.3<br/>LLM Integration\"]\n FASTAPI[\"fastapi<br/>Web Framework\"]\n DOCKER_PY[\"docker<br/>Container Interface\"]\n AIOHTTP[\"aiohttp >=3.9.0<br/>HTTP Client\"]\n end\n \n TOOL_POETRY --> DEPENDENCIES\n TOOL_POETRY --> GROUPS\n TOOL_POETRY --> EXTRAS\n DEPENDENCIES --> LITELLM\n DEPENDENCIES --> FASTAPI\n DEPENDENCIES --> DOCKER_PY\n DEPENDENCIES --> AIOHTTP\n \n GROUPS --> DEV\n GROUPS --> TEST\n GROUPS --> RUNTIME\n GROUPS --> EVALUATION\n```\n\nSources: [pyproject.toml:1-199](), [poetry.lock:1-948]()",
"Python Version and Core Requirements": "The project requires Python `^3.12,<3.14` as specified in [pyproject.toml:28](). Key dependency categories include:\n\n['**LLM Integration**: `litellm`, `openai`, `anthropic` with specific version constraints', '**Web Framework**: `fastapi`, `uvicorn`, `python-socketio` for the backend server', '**Container Interface**: `docker` for runtime management', '**Development Tools**: `ruff`, `mypy`, `pre-commit` in the dev group', '**Testing**: `pytest` with various plugins in the test group']",
"Dependency Group Usage": "The `install-python-dependencies` target in the Makefile installs dependencies based on the `POETRY_GROUP` environment variable:\n\n```\n# Install specific group\npoetry install --only ${POETRY_GROUP}\n\n# Default: install main groups\npoetry install --with dev,test,runtime\n```\n\nSources: [Makefile:139-175](), [pyproject.toml:108-178]()"
},
"Frontend Dependency Management": {
"Frontend Build System Structure": "```\ngraph TB\n subgraph \"package.json Configuration\"\n DEPENDENCIES[\"dependencies<br/>Runtime Libraries\"]\n DEV_DEPS[\"devDependencies<br/>Build Tools\"]\n SCRIPTS[\"scripts<br/>Build Commands\"]\n ENGINES[\"engines<br/>Node.js >= 22.0.0\"]\n end\n \n subgraph \"Core Frontend Dependencies\"\n REACT[\"react ^19.1.1<br/>UI Framework\"]\n REACT_ROUTER[\"@react-router/*<br/>Routing System\"]\n REDUX[\"@reduxjs/toolkit<br/>State Management\"]\n VITE[\"vite ^7.1.4<br/>Build Tool\"]\n TAILWIND[\"tailwindcss<br/>CSS Framework\"]\n end\n \n subgraph \"Build Scripts\"\n DEV_SCRIPT[\"dev<br/>Development Server\"]\n BUILD_SCRIPT[\"build<br/>Production Build\"]\n TEST_SCRIPT[\"test<br/>Unit Testing\"]\n LINT_SCRIPT[\"lint<br/>Code Quality\"]\n TYPECHECK[\"typecheck<br/>TypeScript Validation\"]\n end\n \n subgraph \"Development Tools\"\n TYPESCRIPT[\"typescript ^5.9.2<br/>Type System\"]\n ESLINT[\"eslint ^8.57.0<br/>Linting\"]\n PRETTIER[\"prettier ^3.6.2<br/>Formatting\"]\n PLAYWRIGHT[\"@playwright/test<br/>E2E Testing\"]\n HUSKY[\"husky<br/>Git Hooks\"]\n end\n \n DEPENDENCIES --> REACT\n DEPENDENCIES --> REACT_ROUTER\n DEPENDENCIES --> REDUX\n DEPENDENCIES --> VITE\n \n DEV_DEPS --> TYPESCRIPT\n DEV_DEPS --> ESLINT\n DEV_DEPS --> PRETTIER\n DEV_DEPS --> PLAYWRIGHT\n \n SCRIPTS --> DEV_SCRIPT\n SCRIPTS --> BUILD_SCRIPT\n SCRIPTS --> TEST_SCRIPT\n SCRIPTS --> LINT_SCRIPT\n```\n\nSources: [frontend/package.json:1-152](), [frontend/package-lock.json:1-748]()",
"Frontend Build Scripts": "The frontend defines several npm scripts for different development phases:\n\n| Script | Purpose | Command |\n|--------|---------|---------|\n| `dev` | Development server | `react-router dev` with i18n setup |\n| `build` | Production build | `react-router build` with optimization |\n| `test` | Unit testing | `vitest run` |\n| `lint` | Code quality check | `eslint` + `prettier` + `tsc` |\n| `typecheck` | TypeScript validation | `react-router typegen && tsc` |\n\nSources: [frontend/package.json:63-82]()"
},
"Build Orchestration": {
"Makefile Target Dependencies": "```\ngraph TD\n subgraph \"Primary Targets\"\n BUILD[\"build<br/>Complete Build Process\"]\n RUN[\"run<br/>Start Application\"]\n LINT[\"lint<br/>Code Quality Checks\"]\n TEST[\"test<br/>Run Test Suites\"]\n end\n \n subgraph \"Dependency Checks\"\n CHECK_DEPS[\"check-dependencies<br/>Verify System Requirements\"]\n CHECK_PYTHON[\"check-python<br/>Python 3.12 Validation\"]\n CHECK_NODEJS[\"check-nodejs<br/>Node.js >= 22 Validation\"]\n CHECK_DOCKER[\"check-docker<br/>Docker Installation\"]\n CHECK_POETRY[\"check-poetry<br/>Poetry >= 1.8 Validation\"]\n end\n \n subgraph \"Installation Targets\"\n INSTALL_PYTHON[\"install-python-dependencies<br/>Poetry Install\"]\n INSTALL_FRONTEND[\"install-frontend-dependencies<br/>npm install\"]\n INSTALL_PRECOMMIT[\"install-pre-commit-hooks<br/>Code Quality Setup\"]\n end\n \n subgraph \"Build Targets\"\n BUILD_FRONTEND[\"build-frontend<br/>Production Frontend\"]\n START_BACKEND[\"start-backend<br/>uvicorn Server\"]\n START_FRONTEND[\"start-frontend<br/>Development Server\"]\n end\n \n BUILD --> CHECK_DEPS\n BUILD --> INSTALL_PYTHON\n BUILD --> INSTALL_FRONTEND\n BUILD --> INSTALL_PRECOMMIT\n BUILD --> BUILD_FRONTEND\n \n CHECK_DEPS --> CHECK_PYTHON\n CHECK_DEPS --> CHECK_NODEJS\n CHECK_DEPS --> CHECK_DOCKER\n CHECK_DEPS --> CHECK_POETRY\n \n RUN --> BUILD\n RUN --> START_BACKEND\n RUN --> START_FRONTEND\n \n LINT --> INSTALL_PRECOMMIT\n```\n\nSources: [Makefile:24-370]()",
"Key Makefile Variables": "The Makefile defines several configurable variables for build customization:\n\n| Variable | Default | Purpose |\n|----------|---------|---------|\n| `BACKEND_HOST` | \"127.0.0.1\" | Backend server bind address |\n| `BACKEND_PORT` | 3000 | Backend server port |\n| `FRONTEND_HOST` | \"127.0.0.1\" | Frontend server bind address |\n| `FRONTEND_PORT` | 3001 | Frontend development server port |\n| `PYTHON_VERSION` | 3.12 | Required Python version |\n| `PRE_COMMIT_CONFIG_PATH` | \"./dev_config/python/.pre-commit-config.yaml\" | Pre-commit configuration |\n\nSources: [Makefile:4-16]()"
},
"Container Build System": {
"Container Build Architecture": "```\ngraph TB\n subgraph \"Build Script System\"\n BUILD_SH[\"containers/build.sh<br/>Universal Build Script\"]\n CONFIG_SH[\"containers/*/config.sh<br/>Image Configuration\"]\n end\n \n subgraph \"Container Types\"\n APP_CONTAINER[\"openhands<br/>containers/app/Dockerfile\"]\n RUNTIME_CONTAINER[\"runtime<br/>containers/runtime/Dockerfile\"]\n DEV_CONTAINER[\"dev<br/>containers/dev/Dockerfile\"]\n end\n \n subgraph \"Docker Compose Configurations\"\n DEV_COMPOSE[\"containers/dev/compose.yml<br/>Development Environment\"]\n PROD_COMPOSE[\"docker-compose.yml<br/>Production Deployment\"]\n end\n \n subgraph \"Build Parameters\"\n IMAGE_NAME[\"-i image_name<br/>Container Image Name\"]\n ORG_NAME[\"-o org_name<br/>Registry Organization\"]\n PUSH_FLAG[\"--push<br/>Registry Push\"]\n LOAD_FLAG[\"--load<br/>Local Load\"]\n TAG_SUFFIX[\"-t tag_suffix<br/>Version Suffix\"]\n end\n \n BUILD_SH --> CONFIG_SH\n BUILD_SH --> APP_CONTAINER\n BUILD_SH --> RUNTIME_CONTAINER\n \n CONFIG_SH --> IMAGE_NAME\n CONFIG_SH --> ORG_NAME\n \n BUILD_SH --> PUSH_FLAG\n BUILD_SH --> LOAD_FLAG\n BUILD_SH --> TAG_SUFFIX\n \n DEV_COMPOSE --> DEV_CONTAINER\n PROD_COMPOSE --> APP_CONTAINER\n```\n\nSources: [containers/build.sh:1-183](), [containers/dev/compose.yml:1-40](), [docker-compose.yml:1-24]()",
"Container Build Script Usage": "The `containers/build.sh` script provides a unified interface for building different container images:\n\n```\n# Build application container\n./containers/build.sh -i openhands --load\n\n# Build and push runtime container\n./containers/build.sh -i runtime -o all-hands-ai --push\n\n# Build with custom tag\n./containers/build.sh -i openhands -t dev-$(git rev-parse --short HEAD)\n```\n\nThe script automatically handles:\n\n['Multi-platform builds (linux/amd64, linux/arm64)', 'Registry caching for faster builds', 'Git-based tagging from `GITHUB_REF_NAME` and `RELEVANT_SHA`', 'Build argument injection (`OPENHANDS_BUILD_VERSION`)']\n\nSources: [containers/build.sh:24-183]()"
},
"CI/CD Integration": {
"CI/CD Workflow Structure": "```\ngraph TB\n subgraph \"Lint Workflows\"\n LINT_WORKFLOW[\".github/workflows/lint.yml<br/>Code Quality Enforcement\"]\n LINT_FIX[\".github/workflows/lint-fix.yml<br/>Automated Fixes\"]\n LINT_FRONTEND[\"lint-frontend<br/>npm run lint\"]\n LINT_PYTHON[\"lint-python<br/>pre-commit hooks\"]\n LINT_ENTERPRISE[\"lint-enterprise-python<br/>Enterprise Code\"]\n VERSION_CHECK[\"check-version-consistency<br/>Version Validation\"]\n end\n \n subgraph \"Test Workflows\"\n FE_TESTS[\".github/workflows/fe-unit-tests.yml<br/>Frontend Testing\"]\n FE_TEST_JOB[\"fe-test<br/>npm run test:coverage\"]\n end\n \n subgraph \"Maintenance Workflows\"\n STALE[\".github/workflows/stale.yml<br/>Issue Management\"]\n CLEANUP[\".github/workflows/clean-up.yml<br/>Workflow Cleanup\"]\n end\n \n subgraph \"Build Dependencies\"\n NODE_SETUP[\"useblacksmith/setup-node@v5<br/>Node.js 22\"]\n PYTHON_SETUP[\"useblacksmith/setup-python@v6<br/>Python 3.12\"]\n PRECOMMIT_INSTALL[\"pre-commit==3.7.0<br/>Code Quality Tools\"]\n end\n \n LINT_WORKFLOW --> LINT_FRONTEND\n LINT_WORKFLOW --> LINT_PYTHON\n LINT_WORKFLOW --> LINT_ENTERPRISE\n LINT_WORKFLOW --> VERSION_CHECK\n \n LINT_FRONTEND --> NODE_SETUP\n LINT_PYTHON --> PYTHON_SETUP\n LINT_PYTHON --> PRECOMMIT_INSTALL\n \n FE_TESTS --> FE_TEST_JOB\n FE_TEST_JOB --> NODE_SETUP\n```\n\nSources: [.github/workflows/lint.yml:1-88](), [.github/workflows/fe-unit-tests.yml:1-45](), [.github/workflows/lint-fix.yml:1-98]()",
"Automated Quality Enforcement": "The CI system enforces code quality through several mechanisms:\n\n['**Pre-commit Hooks**: Defined in `./dev_config/python/.pre-commit-config.yaml` and run via `pre-commit run --all-files`', '**Frontend Linting**: Uses ESLint, Prettier, and TypeScript compilation checks', '**Version Consistency**: Validates version numbers across documentation and configuration files', '**Automated Fixes**: The `lint-fix` label triggers automated code formatting and correction']\n\nThe lint workflows run on:\n\n['All pushes to `main` branch', 'All pull requests', 'Specific path changes for frontend tests (`frontend/**`)']\n\nSources: [.github/workflows/lint.yml:7-17](), [.github/workflows/fe-unit-tests.yml:6-14]()"
},
"Development Workflow": {
"Local Development Setup": "```\ngraph TD\n subgraph \"Development Commands\"\n MAKE_BUILD[\"make build<br/>Complete Environment Setup\"]\n MAKE_RUN[\"make run<br/>Start Full Application\"]\n MAKE_START_BACKEND[\"make start-backend<br/>Backend Only\"]\n MAKE_START_FRONTEND[\"make start-frontend<br/>Frontend Only\"]\n end\n \n subgraph \"Configuration Setup\"\n SETUP_CONFIG[\"make setup-config<br/>Interactive Configuration\"]\n SETUP_CONFIG_BASIC[\"make setup-config-basic<br/>Default Configuration\"]\n CONFIG_TOML[\"config.toml<br/>Runtime Configuration\"]\n end\n \n subgraph \"Container Development\"\n DOCKER_DEV[\"make docker-dev<br/>Development Container\"]\n DOCKER_RUN[\"make docker-run<br/>Production Container\"]\n DEV_SH[\"./containers/dev/dev.sh<br/>Direct Container Access\"]\n end\n \n subgraph \"Quality Assurance\"\n MAKE_LINT[\"make lint<br/>Code Quality Checks\"]\n MAKE_TEST[\"make test<br/>Run Test Suites\"]\n MAKE_CLEAN[\"make clean<br/>Cache Cleanup\"]\n end\n \n MAKE_BUILD --> MAKE_RUN\n MAKE_RUN --> MAKE_START_BACKEND\n MAKE_RUN --> MAKE_START_FRONTEND\n \n SETUP_CONFIG --> CONFIG_TOML\n SETUP_CONFIG_BASIC --> CONFIG_TOML\n \n DOCKER_DEV --> DEV_SH\n \n MAKE_LINT --> MAKE_BUILD\n MAKE_TEST --> MAKE_BUILD\n```\n\nSources: [Makefile:279-370](), [Development.md:51-140]()",
"Environment Variables and Configuration": "The build system respects several environment variables for customization:\n\n| Variable | Purpose | Default |\n|----------|---------|---------|\n| `POETRY_GROUP` | Poetry dependency group to install | \"dev,test,runtime\" |\n| `INSTALL_PLAYWRIGHT` | Control Playwright installation | true |\n| `INSTALL_DOCKER` | Skip Docker requirement check | unset |\n| `SANDBOX_RUNTIME_CONTAINER_IMAGE` | Override runtime container | ghcr.io/all-hands-ai/runtime:0.56-nikolaik |\n| `WORKSPACE_BASE` | Workspace directory | \"./workspace\" |\n\nThese variables can be set to customize the build process for different environments or development scenarios.\n\nSources: [Makefile:139-175](), [containers/dev/compose.yml:10-17](), [docker-compose.yml:9-12]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
}
]
},
{
"title": "Advanced Features",
"description": null,
"content": {
"Automated Issue Resolution": "OpenHands provides a sophisticated GitHub Actions workflow that automatically resolves issues and pull requests using AI agents. This system can be triggered by labels, comments, or pull request reviews.\n\n```\ngraph TB\n subgraph \"GitHub Events\"\n LABEL[\"Label: fix-me\"]\n COMMENT[\"Comment: @openhands-agent\"]\n REVIEW[\"PR Review: @openhands-agent\"]\n end\n \n subgraph \"Workflow Triggers\"\n TRIGGER[\".github/workflows/openhands-resolver.yml\"]\n PARAMS[\"Parameters<br/>max_iterations<br/>macro<br/>target_branch<br/>LLM_MODEL\"]\n end\n \n subgraph \"Resolution Process\"\n INSTALL[\"Install OpenHands<br/>experimental or stable\"]\n RESOLVE[\"openhands.resolver.resolve_issue<br/>--issue-number<br/>--issue-type<br/>--max-iterations\"]\n OUTPUT[\"output.jsonl<br/>resolution results\"]\n end\n \n subgraph \"PR Creation\"\n SUCCESS{\"Resolution<br/>Success?\"}\n DRAFT_PR[\"openhands.resolver.send_pull_request<br/>--pr-type draft\"]\n BRANCH[\"Create branch<br/>--pr-type branch\"]\n COMMENT_PR[\"GitHub comment<br/>with results\"]\n end\n \n LABEL --> TRIGGER\n COMMENT --> TRIGGER \n REVIEW --> TRIGGER\n TRIGGER --> PARAMS\n PARAMS --> INSTALL\n INSTALL --> RESOLVE\n RESOLVE --> OUTPUT\n OUTPUT --> SUCCESS\n SUCCESS -->|Yes| DRAFT_PR\n SUCCESS -->|No| BRANCH\n DRAFT_PR --> COMMENT_PR\n BRANCH --> COMMENT_PR\n```\n\n**Workflow Configuration**\n\nThe resolver accepts multiple configuration parameters through workflow inputs and secrets:\n\n['`max_iterations`: Maximum number of agent iterations (default: 50)', '`macro`: Trigger phrase in comments (default: \"@openhands-agent\")', '`LLM_MODEL`: Model to use (default: \"anthropic/claude-sonnet-4-20250514\")', '`base_container_image`: Custom sandbox environment', '`target_branch`: Branch to create PR against (default: \"main\")']\n\n**Trigger Mechanisms**\n\nThe system responds to three types of GitHub events:\n\n['**Label-based**: Issues/PRs labeled with `fix-me` or `fix-me-experimental`', '**Comment-based**: Comments containing the configured macro from collaborators', '**Review-based**: PR reviews containing the macro from authorized users']\n\nSources: [.github/workflows/openhands-resolver.yml:1-434]()",
"Advanced Conversation Management": "OpenHands implements two distinct conversation management strategies depending on deployment requirements.\n\n```\ngraph TB\n subgraph \"ConversationManager Interface\"\n IFACE[\"ConversationManager<br/>Abstract Base Class\"]\n METHODS[\"attach_to_conversation()<br/>join_conversation()<br/>send_to_event_stream()<br/>close_session()\"]\n end\n \n subgraph \"Standalone Implementation\"\n STANDALONE[\"StandaloneConversationManager\"]\n LOCAL_LOOPS[\"_local_agent_loops_by_sid<br/>dict[str, Session]\"]\n LOCAL_CONN[\"_local_connection_id_to_session_id<br/>dict[str, str]\"]\n ACTIVE_CONV[\"_active_conversations<br/>dict[str, tuple[ServerConversation, int]]\"]\n DETACHED_CONV[\"_detached_conversations<br/>dict[str, tuple[ServerConversation, float]]\"]\n end\n \n subgraph \"Docker Nested Implementation\"\n DOCKER[\"DockerNestedConversationManager\"]\n CONTAINERS[\"docker_client.containers.list()<br/>openhands-runtime-{sid}\"]\n NESTED_API[\"Nested Runtime API<br/>httpx requests\"]\n SESSION_KEY[\"_get_session_api_key_for_conversation()\"]\n end\n \n IFACE --> STANDALONE\n IFACE --> DOCKER\n STANDALONE --> LOCAL_LOOPS\n STANDALONE --> LOCAL_CONN\n STANDALONE --> ACTIVE_CONV\n STANDALONE --> DETACHED_CONV\n DOCKER --> CONTAINERS\n DOCKER --> NESTED_API\n DOCKER --> SESSION_KEY\n```\n\n**Standalone Conversation Manager**\n\nThe `StandaloneConversationManager` handles conversations within a single server process. It maintains several key data structures:\n\n['`_local_agent_loops_by_sid`: Maps session IDs to `Session` objects', '`_active_conversations`: Tracks active conversations with reference counts', '`_detached_conversations`: Manages recently disconnected conversations for reuse']\n\nKey features include automatic cleanup of stale conversations and branch tracking for Git operations.\n\n**Docker Nested Conversation Manager** \n\nThe `DockerNestedConversationManager` runs each conversation in its own Docker container. This approach provides better isolation but requires container orchestration:\n\n['Each conversation runs in a container named `openhands-runtime-{sid}`', 'Communication occurs through HTTP API calls to nested runtimes', 'Session API keys provide authentication between parent and nested containers']\n\nSources: [openhands/server/conversation_manager/standalone_conversation_manager.py:53-753](), [openhands/server/conversation_manager/docker_nested_conversation_manager.py:50-618]()",
"Runtime System Advanced Features": {
"Warm Server Pool Management": "```\ngraph LR\n subgraph \"Server Lifecycle\"\n CREATE[\"_create_server()<br/>ActionExecutionServerInfo\"]\n WARM_POOL[\"_WARM_SERVERS<br/>list[ActionExecutionServerInfo]\"]\n RUNNING[\"_RUNNING_SERVERS<br/>dict[str, ActionExecutionServerInfo]\"]\n end\n \n subgraph \"Server Creation Process\"\n PORTS[\"find_available_tcp_port()<br/>execution_server_port<br/>vscode_port<br/>app_ports\"]\n SUBPROCESS[\"subprocess.Popen<br/>action_execution_server\"]\n LOG_THREAD[\"threading.Thread<br/>log_output()\"]\n end\n \n subgraph \"Environment Configuration\"\n ENV_VARS[\"Environment Variables<br/>INITIAL_NUM_WARM_SERVERS<br/>DESIRED_NUM_WARM_SERVERS<br/>LOCAL_RUNTIME_MODE\"]\n WORKSPACE[\"Workspace Setup<br/>tempfile.mkdtemp<br/>workspace_mount_path\"]\n end\n \n CREATE --> WARM_POOL\n WARM_POOL --> RUNNING\n CREATE --> PORTS\n PORTS --> SUBPROCESS\n SUBPROCESS --> LOG_THREAD\n ENV_VARS --> CREATE\n WORKSPACE --> CREATE\n```\n\nThe `LocalRuntime` maintains pools of pre-initialized servers to reduce connection latency:\n\n**Warm Server Creation**: Background processes create ready-to-use server instances\n\n['`INITIAL_NUM_WARM_SERVERS`: Servers created during setup', '`DESIRED_NUM_WARM_SERVERS`: Target pool size maintained during operation']\n\n**Server Reuse Logic**: When connecting to a conversation:\n\n['Check `_RUNNING_SERVERS` for existing server', 'Pop from `_WARM_SERVERS` if available ', 'Create new server if needed', 'Update workspace paths appropriately']\n\n**Resource Management**: Each `ActionExecutionServerInfo` tracks:\n\n['Process handle and port assignments', 'Log thread and exit event for cleanup', 'Temporary workspace path', 'Workspace mount configuration']\n\nSources: [openhands/runtime/impl/local/local_runtime.py:123-568]()"
},
"Plugin System Architecture": "OpenHands supports a flexible plugin system for extending runtime capabilities with development tools.\n\n```\ngraph TB\n subgraph \"Plugin Interface\"\n REQ[\"PluginRequirement<br/>@dataclass\"]\n PLUGIN[\"Plugin<br/>initialize()<br/>run()\"]\n end\n \n subgraph \"VSCode Plugin\"\n VSCODE_REQ[\"VSCodeRequirement<br/>name: 'vscode'\"]\n VSCODE_PLUGIN[\"VSCodePlugin<br/>vscode_port<br/>vscode_connection_token<br/>gateway_process\"]\n OPENVSCODE[\"OpenVSCode Server<br/>--host 0.0.0.0<br/>--connection-token<br/>--disable-workspace-trust\"]\n end\n \n subgraph \"Jupyter Plugin\" \n JUPYTER_REQ[\"JupyterRequirement<br/>name: 'jupyter'\"]\n JUPYTER_PLUGIN[\"JupyterPlugin<br/>kernel_gateway_port<br/>kernel_id<br/>JupyterKernel\"]\n JUPYTER_GATEWAY[\"Jupyter Kernel Gateway<br/>KernelGatewayApp.ip=0.0.0.0<br/>KernelGatewayApp.port\"]\n end\n \n REQ --> VSCODE_REQ\n REQ --> JUPYTER_REQ\n PLUGIN --> VSCODE_PLUGIN\n PLUGIN --> JUPYTER_PLUGIN\n VSCODE_PLUGIN --> OPENVSCODE\n JUPYTER_PLUGIN --> JUPYTER_GATEWAY\n```\n\n**VSCode Plugin Implementation**\n\nThe `VSCodePlugin` provides a web-based development environment:\n\n['Initializes OpenVSCode Server with authentication tokens', 'Configures workspace settings through `.vscode/settings.json`', 'Supports path-based routing with `--server-base-path` flag', 'Handles platform-specific limitations (disabled on Windows)']\n\n**Jupyter Plugin Implementation**\n\nThe `JupyterPlugin` enables interactive Python execution:\n\n['Launches Jupyter Kernel Gateway on available ports', 'Manages `JupyterKernel` instances with WebSocket communication', 'Supports structured output with text and image content', 'Handles execution timeouts and kernel interruption']\n\n**Plugin Lifecycle**: Plugins follow a standard initialization pattern:\n\n['`initialize()` called with username and runtime context', 'Platform compatibility checks and port allocation', 'Subprocess management for external services', 'Connection verification and service readiness']\n\nSources: [openhands/runtime/plugins/vscode/__init__.py:24-142](), [openhands/runtime/plugins/jupyter/__init__.py:22-173]()",
"File Operations & Security": {
"File Upload Configuration System": "```\ngraph TB\n subgraph \"Configuration Loading\"\n CONFIG[\"load_file_upload_config()<br/>OpenHandsConfig\"]\n PARAMS[\"max_file_size_mb<br/>restrict_file_types<br/>allowed_extensions\"]\n VALIDATION[\"Sanity Checks<br/>Extension normalization<br/>Default fallbacks\"]\n end\n \n subgraph \"Security Functions\"\n SANITIZE[\"sanitize_filename()<br/>os.path.basename()<br/>re.sub(r'[^\\\\w\\\\-_\\\\.]', '')\"]\n EXTENSION_CHECK[\"is_extension_allowed()<br/>os.path.splitext()<br/>case-insensitive\"]\n UNIQUE_NAME[\"get_unique_filename()<br/>copy counter logic\"]\n end\n \n subgraph \"File Filtering\"\n IGNORE_LIST[\"FILES_TO_IGNORE<br/>.git/, .DS_Store<br/>node_modules/<br/>__pycache__/<br/>.vscode/\"]\n end\n \n CONFIG --> PARAMS\n PARAMS --> VALIDATION\n VALIDATION --> SANITIZE\n VALIDATION --> EXTENSION_CHECK\n VALIDATION --> UNIQUE_NAME\n IGNORE_LIST --> EXTENSION_CHECK\n```\n\n**Security Implementations**:\n\n['**Filename Sanitization**: `sanitize_filename()` removes directory traversal attempts and limits filename length', '**Extension Validation**: `is_extension_allowed()` enforces whitelist-based file type restrictions ', '**Unique Naming**: `get_unique_filename()` prevents overwrites with copy counter suffixes', '**Path Safety**: Automatic filtering of sensitive directories and system files']\n\n**Configuration Options**:\n\n['`max_file_size_mb`: Size limit enforcement (0 = unlimited)', '`restrict_file_types`: Enable/disable extension filtering', '`allowed_extensions`: Whitelist of permitted file extensions']\n\nSources: [openhands/server/file_config.py:18-140]()"
},
"Evaluation Integration": "OpenHands integrates with external evaluation systems for automated performance testing and benchmarking.\n\n```\ngraph TB\n subgraph \"Trigger Events\"\n PR_LABEL[\"PR Labels<br/>run-eval-1/2/50/100\"]\n RELEASE[\"Release Events<br/>published\"]\n MANUAL[\"Manual Dispatch<br/>workflow_dispatch\"]\n end\n \n subgraph \"Evaluation Parameters\"\n BRANCH_DETECT[\"Branch Detection<br/>github.head_ref<br/>github.ref_name\"]\n INSTANCE_COUNT[\"Instance Count<br/>1, 2, 50, 100\"]\n REMOTE_TRIGGER[\"Remote API Call<br/>All-Hands-AI/evaluation\"]\n end\n \n subgraph \"Result Management\"\n MASTER_ISSUE[\"MASTER_EVAL_ISSUE_NUMBER<br/>centralized results\"]\n SLACK_NOTIFY[\"Slack Integration<br/>evaluation progress\"]\n GITHUB_COMMENTS[\"GitHub Comments<br/>status updates\"]\n end\n \n PR_LABEL --> BRANCH_DETECT\n RELEASE --> BRANCH_DETECT\n MANUAL --> BRANCH_DETECT\n BRANCH_DETECT --> INSTANCE_COUNT\n INSTANCE_COUNT --> REMOTE_TRIGGER\n REMOTE_TRIGGER --> MASTER_ISSUE\n REMOTE_TRIGGER --> SLACK_NOTIFY\n REMOTE_TRIGGER --> GITHUB_COMMENTS\n```\n\n**Evaluation Workflow Features**:\n\n['**Multi-trigger Support**: PR labels, releases, or manual dispatch', '**Scalable Testing**: Configurable instance counts (1-100)', '**Branch Flexibility**: Automatic branch detection based on trigger type', '**Centralized Results**: Master issue for non-PR evaluations', '**External Integration**: Remote repository dispatch for evaluation execution']\n\n**Trigger Configuration**:\n\n['Label-based: `run-eval-{1,2,50,100}` labels on PRs', 'Release-based: Automatic evaluation on published releases', 'Manual: Workflow dispatch with custom parameters']\n\nSources: [.github/workflows/run-eval.yml:1-136]()"
},
"metadata": {
"source": "deepwiki"
},
"subpages": [
{
"title": "Automated Issue Resolution",
"description": null,
"content": {
"Overview": "The automated issue resolution system allows repository maintainers to leverage OpenHands agents for automated bug fixes and feature implementations. Users can trigger the resolver by applying specific labels to issues/PRs or mentioning the agent in comments. The system runs in isolated sandbox environments and produces either successful pull requests or diagnostic branches with attempted changes.\n\nSources: [.github/workflows/openhands-resolver.yml:1-434]()",
"Trigger Mechanisms": "The resolver supports multiple activation methods through GitHub webhook events:\n\n| Trigger Type | Event | Condition |\n|--------------|-------|-----------|\n| Label-based | `issues.labeled`, `pull_request.labeled` | Label name is `fix-me` or `fix-me-experimental` |\n| Comment-based | `issue_comment.created` | Comment contains configurable macro (default: `@openhands-agent`) |\n| PR Review | `pull_request_review_comment.created`, `pull_request_review.submitted` | Review contains agent macro |\n| Programmatic | `workflow_call` | Direct workflow invocation |\n\nComment-based triggers require the commenter to have `OWNER`, `COLLABORATOR`, or `MEMBER` association with the repository.\n\nSources: [.github/workflows/openhands-resolver.yml:53-85]()",
"Workflow Architecture": {
"Main Workflow Structure": "```\ngraph TD\n subgraph \"GitHub Events\"\n LABEL[\"issues.labeled<br/>pull_request.labeled\"]\n COMMENT[\"issue_comment.created<br/>pr_review_comment.created\"]\n REVIEW[\"pull_request_review.submitted\"]\n CALL[\"workflow_call\"]\n end\n \n subgraph \"Condition Evaluation\"\n COND[\"Trigger Condition Check<br/>Labels: fix-me, fix-me-experimental<br/>Comments: @openhands-agent<br/>Authorization: OWNER/COLLABORATOR/MEMBER\"]\n end\n \n subgraph \"Environment Setup\"\n CHECKOUT[\"actions/checkout@v4\"]\n PYTHON[\"actions/setup-python@v5<br/>Python 3.12\"]\n CACHE[\"actions/cache@v4<br/>pip dependencies\"]\n INSTALL[\"Install OpenHands<br/>Stable or Experimental\"]\n end\n \n subgraph \"Resolution Process\"\n RESOLVE[\"openhands.resolver.resolve_issue<br/>--selected-repo<br/>--issue-number<br/>--issue-type<br/>--max-iterations\"]\n CHECK[\"Check output.jsonl<br/>success: true/false\"]\n UPLOAD[\"Upload Artifacts<br/>resolver-output\"]\n end\n \n subgraph \"Output Handling\"\n PR[\"openhands.resolver.send_pull_request<br/>Create Draft PR\"]\n BRANCH[\"Create Diagnostic Branch<br/>On Failure\"]\n COMMENT[\"GitHub Comments<br/>Status Updates\"]\n end\n \n LABEL --> COND\n COMMENT --> COND\n REVIEW --> COND\n CALL --> COND\n \n COND --> CHECKOUT\n CHECKOUT --> PYTHON\n PYTHON --> CACHE\n CACHE --> INSTALL\n \n INSTALL --> RESOLVE\n RESOLVE --> CHECK\n CHECK --> UPLOAD\n \n CHECK --> PR\n CHECK --> BRANCH\n PR --> COMMENT\n BRANCH --> COMMENT\n```\n\nSources: [.github/workflows/openhands-resolver.yml:69-434]()",
"Module Integration": "```\ngraph LR\n subgraph \"GitHub Actions Workflow\"\n WORKFLOW[\"openhands-resolver.yml<br/>GitHub Actions Pipeline\"]\n end\n \n subgraph \"OpenHands Resolver Modules\"\n RESOLVE[\"openhands.resolver.resolve_issue<br/>Main Resolution Logic\"]\n SENDPR[\"openhands.resolver.send_pull_request<br/>PR/Branch Creation\"]\n OUTPUT[\"output/output.jsonl<br/>Resolution Results\"]\n end\n \n subgraph \"Core OpenHands Platform\"\n AGENT[\"Agent System<br/>Code Analysis & Generation\"]\n RUNTIME[\"Runtime Environment<br/>Sandbox Execution\"]\n LLM[\"LLM Integration<br/>Model Communication\"]\n end\n \n subgraph \"External Services\"\n GITHUB[\"GitHub API<br/>Repository Operations\"]\n REGISTRY[\"Package Registry<br/>OpenHands Installation\"]\n end\n \n WORKFLOW --> RESOLVE\n WORKFLOW --> SENDPR\n RESOLVE --> OUTPUT\n \n RESOLVE --> AGENT\n AGENT --> RUNTIME\n AGENT --> LLM\n \n SENDPR --> GITHUB\n WORKFLOW --> REGISTRY\n```\n\nSources: [.github/workflows/openhands-resolver.yml:254-260](), [.github/workflows/openhands-resolver.yml:292-304]()"
},
"Resolution Process": {
"Issue Analysis Phase": "The resolver begins by analyzing the target issue or pull request using the `openhands.resolver.resolve_issue` module with the following parameters:\n\n['`--selected-repo`: Target repository in format `owner/name`', '`--issue-number`: GitHub issue or PR number', '`--issue-type`: Either `issue` or `pr`', '`--max-iterations`: Maximum agent iterations (default: 50)', '`--comment-id`: Optional comment ID for context', '`--is-experimental`: Boolean flag for experimental features']\n\nSources: [.github/workflows/openhands-resolver.yml:254-260]()",
"Agent Execution Environment": "The resolver configures the OpenHands agent with specific environment variables:\n\n```\nGITHUB_TOKEN: Repository access token\nGITHUB_USERNAME: Agent username for commits\nLLM_MODEL: Language model specification\nLLM_API_KEY: Model API credentials\nSANDBOX_ENV_GITHUB_TOKEN: Sandbox GitHub access\nSANDBOX_BASE_CONTAINER_IMAGE: Custom container image\n```\n\nThe agent operates within a sandboxed runtime environment with access to repository contents and development tools.\n\nSources: [.github/workflows/openhands-resolver.yml:244-252]()",
"Success Determination": "Resolution success is determined by parsing the `output/output.jsonl` file for a JSON object containing `\"success\":true`. This file contains structured data about the agent's execution including:\n\n['Success/failure status', 'Result explanations for failed attempts ', 'Generated code changes', 'Execution metadata']\n\nSources: [.github/workflows/openhands-resolver.yml:264-269]()"
},
"Output Handling": {
"Successful Resolutions": "When resolution succeeds (`\"success\":true` in output.jsonl), the system:\n\n['Executes `openhands.resolver.send_pull_request` with parameters:', ['`--issue-number`: Original issue number', '`--target-branch`: Base branch for PR (default: `main`)', '`--pr-type`: Either `draft` or `ready`', '`--reviewer`: Assigns the triggering user as reviewer'], \"Creates a draft pull request with the agent's proposed changes\", 'Comments on the original issue linking to the new PR']\n\nSources: [.github/workflows/openhands-resolver.yml:291-297]()",
"Failed Resolutions": "When resolution fails, the system:\n\n['Creates a diagnostic branch named after the issue', 'Pushes any partial changes made during the attempt', 'Comments on the original issue with:', ['Link to the diagnostic branch', 'Failure explanation from `output.jsonl`', 'Manual intervention guidance']]\n\nThe diagnostic branch allows maintainers to review the agent's partial progress and continue work manually.\n\nSources: [.github/workflows/openhands-resolver.yml:298-304](), [.github/workflows/openhands-resolver.yml:401-415]()",
"Artifact Preservation": "All resolver executions produce artifacts stored for 30 days:\n\n['**resolver-output**: Contains `output.jsonl` with complete execution logs', 'Artifacts are uploaded regardless of success/failure for debugging']\n\nSources: [.github/workflows/openhands-resolver.yml:271-277]()"
},
"Configuration Options": {
"Workflow Inputs": "The resolver workflow accepts the following configuration inputs:\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `max_iterations` | number | 50 | Maximum agent execution cycles |\n| `macro` | string | \"@openhands-agent\" | Comment trigger phrase |\n| `target_branch` | string | \"main\" | Base branch for PRs |\n| `pr_type` | string | \"draft\" | PR creation mode |\n| `LLM_MODEL` | string | \"anthropic/claude-sonnet-4-20250514\" | Language model |\n| `LLM_API_VERSION` | string | \"\" | Model API version |\n| `base_container_image` | string | \"\" | Custom sandbox image |\n| `runner` | string | \"ubuntu-latest\" | GitHub Actions runner |\n\nSources: [.github/workflows/openhands-resolver.yml:5-41]()",
"Secret Management": "Required and optional secrets for resolver operation:\n\n| Secret | Required | Purpose |\n|--------|----------|---------|\n| `LLM_API_KEY` | Yes | Language model authentication |\n| `LLM_MODEL` | No | Override model selection |\n| `LLM_BASE_URL` | No | Custom model endpoint |\n| `PAT_TOKEN` | No | GitHub personal access token |\n| `PAT_USERNAME` | No | Custom commit username |\n\nThe system falls back to `GITHUB_TOKEN` when `PAT_TOKEN` is unavailable, and uses \"openhands-agent\" as default username.\n\nSources: [.github/workflows/openhands-resolver.yml:42-51](), [.github/workflows/openhands-resolver.yml:128-158]()",
"Installation Modes": "The resolver supports two installation modes based on trigger type:\n\n['**Stable Mode**: Installs latest published version from PyPI', '**Experimental Mode**: Installs from GitHub main branch for cutting-edge features']\n\nExperimental mode is triggered by:\n\n['`fix-me-experimental` label', '`@openhands-agent-exp` in comments', 'Workflow parameter configuration']\n\nSources: [.github/workflows/openhands-resolver.yml:207-242]()"
}
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
},
{
"title": "File Operations & Security",
"description": null,
"content": {
"Overview": "OpenHands operates in sandboxed environments where AI agents need to read, write, and manipulate files safely. The file operations system provides secure path resolution that prevents directory traversal attacks and ensures agents can only access files within their designated workspace boundaries.\n\nThe core security model maps between three path contexts:\n\n['**Container paths**: Paths as seen inside the Docker container (e.g., `/workspace/file.txt`)', '**Host paths**: Corresponding paths on the host system (e.g., `workspace/file.txt`) ', '**Sandbox paths**: Virtual paths used by agents for workspace operations']",
"File Path Resolution Architecture": "```\ngraph TB\n subgraph \"Agent Layer\"\n AGENT[\"Agent Action Request\"]\n RELATIVE[\"Relative Path<br/>('file.txt', 'subdir/file.txt')\"]\n ABSOLUTE[\"Absolute Path<br/>('/workspace/file.txt')\"]\n end\n \n subgraph \"Path Resolution System\"\n RESOLVE[\"resolve_path() Function\"]\n SECURITY[\"Security Validation\"]\n NORMALIZE[\"Path Normalization\"]\n end\n \n subgraph \"Path Contexts\"\n CONTAINER[\"/workspace<br/>(Container Path)\"]\n HOST[\"workspace/<br/>(Host Path)\"]\n SANDBOX[\"/workspace<br/>(Sandbox Prefix)\"]\n end\n \n subgraph \"Security Checks\"\n TRAVERSAL[\"Path Traversal Detection\"]\n BOUNDARY[\"Workspace Boundary Check\"]\n PERMISSION[\"Permission Validation\"]\n end\n \n AGENT --> RELATIVE\n AGENT --> ABSOLUTE\n \n RELATIVE --> RESOLVE\n ABSOLUTE --> RESOLVE\n \n RESOLVE --> SECURITY\n SECURITY --> TRAVERSAL\n SECURITY --> BOUNDARY\n SECURITY --> PERMISSION\n \n SECURITY --> NORMALIZE\n NORMALIZE --> CONTAINER\n NORMALIZE --> HOST\n \n SANDBOX --> RESOLVE\n \n TRAVERSAL -->|\"Raises PermissionError\"| AGENT\n BOUNDARY -->|\"Raises PermissionError\"| AGENT\n PERMISSION -->|\"Raises PermissionError\"| AGENT\n```\n\nThe path resolution system ensures that all file operations are validated and constrained within the sandbox workspace boundaries.\n\nSources: [tests/test_fileops.py:1-67]()",
"Security Implementation": {
"Path Traversal Prevention": "The `resolve_path` function in `openhands.runtime.utils.files` implements several security measures:\n\n```\ngraph LR\n subgraph \"Input Validation\"\n INPUT[\"File Path Input\"]\n RELATIVE_CHECK[\"Check for '../' patterns\"]\n ABSOLUTE_CHECK[\"Check for absolute paths\"]\n ROOT_CHECK[\"Check for root access\"]\n end\n \n subgraph \"Security Boundaries\"\n WORKSPACE_PREFIX[\"Workspace Prefix Validation\"]\n NORMALIZED[\"Path Normalization\"]\n BOUNDARY_CHECK[\"Boundary Validation\"]\n end\n \n subgraph \"Security Actions\"\n ALLOW[\"Allow Operation\"]\n DENY[\"Raise PermissionError\"]\n end\n \n INPUT --> RELATIVE_CHECK\n INPUT --> ABSOLUTE_CHECK\n INPUT --> ROOT_CHECK\n \n RELATIVE_CHECK -->|\"Contains '..'\"| DENY\n ABSOLUTE_CHECK -->|\"Outside workspace\"| DENY \n ROOT_CHECK -->|\"Accesses '/'\"| DENY\n \n RELATIVE_CHECK -->|\"Safe\"| WORKSPACE_PREFIX\n ABSOLUTE_CHECK -->|\"Within workspace\"| WORKSPACE_PREFIX\n ROOT_CHECK -->|\"Safe\"| WORKSPACE_PREFIX\n \n WORKSPACE_PREFIX --> NORMALIZED\n NORMALIZED --> BOUNDARY_CHECK\n BOUNDARY_CHECK -->|\"Within bounds\"| ALLOW\n BOUNDARY_CHECK -->|\"Outside bounds\"| DENY\n```\n\nThe system prevents common attack vectors:\n\n['**Directory traversal**: Paths containing `../` are rejected', '**Absolute path escape**: Paths outside the workspace root are blocked ', '**Root filesystem access**: Direct access to `/` or system directories is denied']\n\nSources: [tests/test_fileops.py:48-62]()"
},
"Path Resolution Examples": {
"Valid Path Resolution": "For allowed paths, the resolution process follows these steps:\n\n['**Input normalization**: Convert relative paths to absolute workspace paths', '**Path cleaning**: Resolve `..` and `.` components safely within workspace bounds', '**Boundary validation**: Ensure the resolved path stays within the designated workspace', '**Host mapping**: Map the container path to the corresponding host filesystem path']\n\nSources: [tests/test_fileops.py:12-47]()"
},
"Integration with Runtime System": "```\ngraph TB\n subgraph \"Agent Actions\"\n READ_ACTION[\"FileReadAction\"]\n WRITE_ACTION[\"FileWriteAction\"] \n LIST_ACTION[\"FileListAction\"]\n end\n \n subgraph \"Runtime Layer\"\n ACTION_EXECUTOR[\"ActionExecutionServer\"]\n RUNTIME_CLIENT[\"Runtime Client\"]\n end\n \n subgraph \"File Operations\"\n PATH_RESOLVER[\"resolve_path()\"]\n FILE_HANDLER[\"File Handler\"]\n PERMISSION_CHECK[\"Permission Validator\"]\n end\n \n subgraph \"Execution Environment\"\n DOCKER_CONTAINER[\"Docker Container\"]\n HOST_FILESYSTEM[\"Host Filesystem\"]\n WORKSPACE_MOUNT[\"Workspace Mount\"]\n end\n \n READ_ACTION --> ACTION_EXECUTOR\n WRITE_ACTION --> ACTION_EXECUTOR\n LIST_ACTION --> ACTION_EXECUTOR\n \n ACTION_EXECUTOR --> RUNTIME_CLIENT\n RUNTIME_CLIENT --> PATH_RESOLVER\n \n PATH_RESOLVER --> PERMISSION_CHECK\n PERMISSION_CHECK -->|\"Validated\"| FILE_HANDLER\n PERMISSION_CHECK -->|\"Denied\"| ACTION_EXECUTOR\n \n FILE_HANDLER --> DOCKER_CONTAINER\n DOCKER_CONTAINER --> WORKSPACE_MOUNT\n WORKSPACE_MOUNT --> HOST_FILESYSTEM\n```\n\nFile operations flow through the runtime system where each path is validated before any filesystem access occurs. This ensures that even if an agent attempts unauthorized file access, the security layer blocks it at the path resolution stage.\n\nSources: [tests/test_fileops.py:7-10]()",
"Workspace Configuration": "The file operations system supports flexible workspace configuration through several parameters:\n\n['**`sandbox_path_prefix`**: The path prefix within the sandbox environment (typically `/workspace`)', '**`container_path`**: The mounted path inside the Docker container ', '**`host_path`**: The corresponding directory on the host system', '**`workspace_subdir`**: Optional subdirectory within the workspace for additional isolation']\n\nThis configuration allows OpenHands to operate in various deployment scenarios while maintaining consistent security boundaries.\n\nSources: [tests/test_fileops.py:7-10](), [tests/test_fileops.py:64-66]()"
},
"metadata": {
"source": "deepwiki"
},
"subpages": []
}
]
}
]
}