Skip to content

Commit 83b676c

Browse files
Document custom visualizer feature
- Added comprehensive guide for using custom ConversationVisualizer - Shows the new direct API: visualize=custom_visualizer - Includes examples of highlight patterns and customization options - Documents the improvement over the old callback-based approach Related to: OpenHands/software-agent-sdk#1025 Co-authored-by: openhands <[email protected]>
1 parent eef899c commit 83b676c

File tree

1 file changed

+192
-0
lines changed

1 file changed

+192
-0
lines changed
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
---
2+
title: Custom Visualizer
3+
description: Customize conversation visualization with custom highlighting patterns and display options.
4+
---
5+
6+
<Note>
7+
This example is available on GitHub: [examples/01_standalone_sdk/20_custom_visualizer.py](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/20_custom_visualizer.py)
8+
</Note>
9+
10+
Customize how your agent's conversation is displayed by passing a custom `ConversationVisualizer` instance directly to the `visualize` parameter:
11+
12+
```python icon="python" expandable examples/01_standalone_sdk/20_custom_visualizer.py
13+
"""Example demonstrating custom visualizer usage.
14+
15+
This example shows how to pass a custom ConversationVisualizer directly
16+
to the Conversation, making it easy to customize the visualization without
17+
the need for callbacks.
18+
"""
19+
20+
import os
21+
22+
from pydantic import SecretStr
23+
24+
from openhands.sdk import LLM, Agent, Conversation
25+
from openhands.sdk.conversation.visualizer import ConversationVisualizer
26+
27+
28+
def main():
29+
# Get API key from environment
30+
api_key = os.environ.get("LLM_API_KEY")
31+
if not api_key:
32+
raise ValueError("LLM_API_KEY environment variable is not set")
33+
34+
# Create LLM and Agent
35+
llm = LLM(model="gpt-4o-mini", api_key=SecretStr(api_key))
36+
agent = Agent(llm=llm, tools=[])
37+
38+
# Create a custom visualizer with specific highlighting
39+
custom_visualizer = ConversationVisualizer(
40+
highlight_regex={
41+
r"^Reasoning:": "bold cyan",
42+
r"^Thought:": "bold green",
43+
r"^Action:": "bold yellow",
44+
},
45+
skip_user_messages=False, # Show user messages
46+
)
47+
48+
# Pass the custom visualizer directly to the conversation
49+
# This is more intuitive than visualize=False + callbacks=[...]
50+
conversation = Conversation(
51+
agent=agent,
52+
workspace="./workspace",
53+
visualize=custom_visualizer, # Direct and clear!
54+
)
55+
56+
# Send a message and run
57+
conversation.send_message("What is 2 + 2?")
58+
conversation.run()
59+
60+
print("\n✅ Example completed!")
61+
print("The conversation used a custom visualizer with custom highlighting.")
62+
63+
64+
if __name__ == "__main__":
65+
main()
66+
```
67+
68+
```bash Running the Example
69+
export LLM_API_KEY="your-api-key"
70+
cd agent-sdk
71+
uv run python examples/01_standalone_sdk/20_custom_visualizer.py
72+
```
73+
74+
## Creating a Custom Visualizer
75+
76+
Configure a `ConversationVisualizer` with custom highlighting patterns:
77+
78+
```python
79+
from openhands.sdk.conversation.visualizer import ConversationVisualizer
80+
81+
custom_visualizer = ConversationVisualizer(
82+
highlight_regex={
83+
r"^Reasoning:": "bold cyan",
84+
r"^Thought:": "bold green",
85+
r"^Action:": "bold yellow",
86+
},
87+
skip_user_messages=False, # Show user messages
88+
)
89+
```
90+
91+
### Visualization Options
92+
93+
The `visualize` parameter accepts three types:
94+
95+
- **`True`** (default): Use the default visualizer with standard formatting
96+
- **`False` or `None`**: Disable visualization entirely
97+
- **`ConversationVisualizer` instance**: Use your custom visualizer
98+
99+
### Before and After
100+
101+
**Previous approach** (confusing):
102+
```python
103+
# Had to set visualize=False and pass callback manually
104+
conversation = Conversation(
105+
agent=agent,
106+
workspace=cwd,
107+
visualize=False, # Confusing: we DO want visualization!
108+
callbacks=[custom_visualizer.on_event],
109+
)
110+
```
111+
112+
**New approach** (clear and direct):
113+
```python
114+
# Pass the visualizer directly
115+
conversation = Conversation(
116+
agent=agent,
117+
workspace=cwd,
118+
visualize=custom_visualizer, # Direct and clear!
119+
)
120+
```
121+
122+
## Customization Options
123+
124+
### Highlight Patterns
125+
126+
Use regex patterns to highlight specific content:
127+
128+
```python
129+
highlight_regex={
130+
r"^Reasoning:": "bold cyan", # Lines starting with "Reasoning:"
131+
r"^Thought:": "bold green", # Lines starting with "Thought:"
132+
r"^Action:": "bold yellow", # Lines starting with "Action:"
133+
r"\[ERROR\]": "bold red", # Error markers
134+
r"\[SUCCESS\]": "bold green", # Success markers
135+
}
136+
```
137+
138+
### Available Colors and Styles
139+
140+
Colors: `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`
141+
142+
Styles: `bold`, `dim`, `italic`, `underline`
143+
144+
Combine them: `"bold cyan"`, `"underline red"`, `"bold italic green"`
145+
146+
### Message Filtering
147+
148+
Control which messages are displayed:
149+
150+
```python
151+
ConversationVisualizer(
152+
skip_user_messages=False, # Show user messages (default: True)
153+
skip_system_messages=False, # Show system messages (default: False)
154+
)
155+
```
156+
157+
## Advanced Usage
158+
159+
### Combining with Callbacks
160+
161+
You can still use custom callbacks alongside a custom visualizer:
162+
163+
```python
164+
def my_callback(event):
165+
# Custom logging or processing
166+
print(f"Event received: {event.event_type}")
167+
168+
conversation = Conversation(
169+
agent=agent,
170+
workspace=cwd,
171+
visualize=custom_visualizer,
172+
callbacks=[my_callback], # Additional callbacks
173+
)
174+
```
175+
176+
### Disabling Visualization
177+
178+
To disable visualization entirely:
179+
180+
```python
181+
conversation = Conversation(
182+
agent=agent,
183+
workspace=cwd,
184+
visualize=None, # or False
185+
)
186+
```
187+
188+
## Next Steps
189+
190+
- **[Callbacks](/sdk/guides/convo-async)** - Learn about custom event callbacks
191+
- **[Persistence](/sdk/guides/convo-persistence)** - Save and restore conversation state
192+
- **[Pause and Resume](/sdk/guides/convo-pause-and-resume)** - Control agent execution flow

0 commit comments

Comments
 (0)