Skip to content

Commit 9698f86

Browse files
DidierRLopespiiq
andauthored
Custom agent features and user feedback docs (#153)
* custom agent features and user feedback * improve custom agent features * Update links --------- Co-authored-by: Theodore Aptekarev <aptekarev@gmail.com>
1 parent 33000f4 commit 9698f86

4 files changed

Lines changed: 284 additions & 42 deletions

File tree

content/workspace/developers/ai-features/custom-agent-features.md

Lines changed: 100 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ title: Custom agent features
33
sidebar_position: 8
44
description: Configure and manage custom agent features based on workspace options
55
keywords:
6-
- features
7-
- configuration
8-
- workspace options
9-
- custom agents
10-
- SSE
6+
- features
7+
- configuration
8+
- workspace options
9+
- custom agents
10+
- SSE
1111
---
1212

1313
import HeadTitle from '@site/src/components/General/HeadTitle.tsx';
@@ -18,9 +18,9 @@ Create agents that can dynamically enable or disable features based on workspace
1818

1919
Reference implementation in [this GitHub repository](https://github.com/OpenBB-finance/agents-for-openbb/tree/main/37-vanilla-agent-custom-features).
2020

21-
<img className="pro-border-gradient" width="500" alt="Custom agent features - on and off" src="https://openbb-cms.directus.app/assets/f304643a-654b-4156-a4c4-dea934d18012.png" />
21+
<img className="pro-border-gradient" width="500" alt="Custom agent features - on and off" src="https://openbb-cms.directus.app/assets/f6d38500-4a9a-41e9-93b3-5579f2cb24c0.png" />
2222

23-
<img className="pro-border-gradient" width="500" alt="Custom agent features - on and on" src="https://openbb-cms.directus.app/assets/aa51354c-b611-4c99-829c-cf6e35eb884b.png" />
23+
<img className="pro-border-gradient" width="500" alt="Custom agent features - on and off" src="https://openbb-cms.directus.app/assets/b7b268df-e576-4cc7-837d-d7358fef23bb.png" />
2424

2525
## Architecture
2626

@@ -44,21 +44,42 @@ return JSONResponse(content={
4444
"description": "Allows the copilot to do deep research",
4545
},
4646
"web-search": {
47-
"label": "Web Search",
47+
"label": "Web Search",
4848
"default": True,
4949
"description": "Allows the copilot to search the web.",
5050
},
51+
"model": {
52+
"label": "Model",
53+
"type": "select",
54+
"default": "claude-sonnet-4-20250514",
55+
"description": "Select the LLM model to use.",
56+
"options": [
57+
{"label": "Claude Opus 4", "value": "claude-opus-4-0-20250514"},
58+
{"label": "Claude Sonnet 4", "value": "claude-sonnet-4-20250514"},
59+
{"label": "GPT-4o", "value": "gpt-4o"},
60+
{"label": "GPT-4o mini", "value": "gpt-4o-mini"},
61+
],
62+
},
63+
"agent-name": {
64+
"label": "Name of Agent",
65+
"type": "text",
66+
"default": "Example Agent",
67+
"description": "Set the name the agent uses to introduce itself.",
68+
"placeholder": "e.g. My Custom Agent",
69+
},
5170
},
5271
}
5372
})
5473
```
5574

5675
### Feature configuration
5776

58-
- **Simple features**: Boolean values for basic on/off features
59-
- **Complex features**: Objects with `label`, `default`, and `description` properties
60-
- **Built-in features**: Standard features like `streaming`, `widget-dashboard-select`, `widget-dashboard-search`
61-
- **Custom features**: User-defined features with custom behavior
77+
- **Boolean features**: Simple on/off toggles.
78+
- Objects with `label`, `default`, and `description` properties
79+
- **Text features**: Free-form string input.
80+
- Objects with `label`, `type: "text"`, `default`, `description`, and optional `placeholder`
81+
- **Select features**: Dropdown selection.
82+
- Objects with `label`, `type: "select"`, `default`, `description`, and `options` (array of `{label, value}` objects)
6283

6384
### Query flow
6485

@@ -70,40 +91,47 @@ return JSONResponse(content={
7091

7192
### OpenBB AI SDK
7293

73-
- `QueryRequest.workspace_options`: List of enabled feature names
94+
- `QueryRequest.workspace_options`: Dictionary of option values keyed by option id
7495
- `message_chunk(text)`: Streams response content with feature-aware messaging
75-
- Feature checking via simple list membership: `"feature-name" in workspace_options`
96+
- Boolean features appear as `true` or `false`: `workspace_options["web-search"]`
97+
- Text and select features appear as string values: `workspace_options["model"]`
7698

7799
## Core logic
78100

79101
```python
80102
from typing import AsyncGenerator
81103
from openbb_ai import message_chunk
82104
from openbb_ai.models import MessageChunkSSE, QueryRequest
83-
from fastapi.responses import JSONResponse
84105
from sse_starlette.sse import EventSourceResponse
85106

86107
@app.post("/v1/query")
87108
async def query(request: QueryRequest) -> EventSourceResponse:
88109
# Access workspace options from request payload
89-
workspace_options = getattr(request, "workspace_options", [])
110+
# Example: {"web-search": true, "model": "gpt-4o", "agent-name": "My Bot"}
111+
workspace_options = getattr(request, "workspace_options", {}) or {}
112+
113+
# Check boolean features
114+
deep_research_enabled = bool(workspace_options.get("deep-research", False))
115+
web_search_enabled = bool(workspace_options.get("web-search", True))
90116

91-
# Check which features are enabled
92-
deep_research_enabled = "deep-research" in workspace_options
93-
web_search_enabled = "web-search" in workspace_options
117+
# Read text/select feature values
118+
model = workspace_options.get("model", "claude-sonnet-4-20250514")
119+
agent_name = workspace_options.get("agent-name", "Example Agent")
94120

95121
# Build feature status message
96122
features_msg = (
97123
f"- Deep Research: {'✅ Enabled' if deep_research_enabled else '❌ Disabled'}\n"
98-
f"- Web Search: {'✅ Enabled' if web_search_enabled else '❌ Disabled'}"
124+
f"- Web Search: {'✅ Enabled' if web_search_enabled else '❌ Disabled'}\n"
125+
f"- Model: {model}\n"
126+
f"- Agent Name: {agent_name}"
99127
)
100128

101129
# Include feature status in system prompt
102130
openai_messages = [
103131
{
104132
"role": "system",
105133
"content": (
106-
"You are a simple greeting agent.\n"
134+
f'Your name is "{agent_name}".\n'
107135
"Greet the user and let them know their current feature settings:\n"
108136
f"{features_msg}\n"
109137
"Keep your response brief and friendly."
@@ -139,36 +167,69 @@ async def query(request: QueryRequest) -> EventSourceResponse:
139167
## Feature types
140168

141169
### Boolean features
142-
Simple on/off switches in the agent descriptor:
170+
171+
Simple on/off toggles with a label and default state:
172+
173+
```python
174+
"features": {
175+
"deep-research": {
176+
"label": "Deep Research",
177+
"default": False,
178+
"description": "Allows the copilot to do deep research",
179+
}
180+
}
181+
```
182+
183+
### Text features
184+
185+
Free-form string input with an optional placeholder:
186+
143187
```python
144188
"features": {
145-
"streaming": True,
146-
"some-feature": False
189+
"agent-name": {
190+
"label": "Name of Agent",
191+
"type": "text",
192+
"default": "Example Agent",
193+
"description": "Set the name the agent uses to introduce itself.",
194+
"placeholder": "e.g. My Custom Agent",
195+
}
147196
}
148197
```
149198

150-
### Complex features
151-
Rich feature objects with metadata:
199+
### Select features
200+
201+
Dropdown selection with a list of options:
202+
152203
```python
153204
"features": {
154-
"research-mode": {
155-
"label": "Research Mode",
156-
"default": True,
157-
"description": "Enables comprehensive research capabilities"
205+
"model": {
206+
"label": "Model",
207+
"type": "select",
208+
"default": "claude-sonnet-4-20250514",
209+
"description": "Select the LLM model to use.",
210+
"options": [
211+
{"label": "Claude Opus 4", "value": "claude-opus-4-0-20250514"},
212+
{"label": "Claude Sonnet 4", "value": "claude-sonnet-4-20250514"},
213+
{"label": "GPT-4o", "value": "gpt-4o"},
214+
{"label": "GPT-4o mini", "value": "gpt-4o-mini"},
215+
],
158216
}
159217
}
160218
```
161219

162-
### Conditional behavior
163-
Adjust agent behavior based on enabled features:
220+
### Reading feature values
221+
222+
Boolean, text, and select values are sent in `workspace_options` as a dictionary keyed by option id:
223+
164224
```python
165-
workspace_options = getattr(request, "workspace_options", [])
225+
workspace_options = getattr(request, "workspace_options", {}) or {}
166226

167-
if "research-mode" in workspace_options:
168-
# Enable research capabilities
227+
# Boolean features
228+
if workspace_options.get("deep-research", False):
229+
# Enable deep research capabilities
169230
pass
170231

171-
if "web-search" in workspace_options:
172-
# Enable web search functionality
173-
pass
174-
```
232+
# Text/select features
233+
model = workspace_options.get("model", "claude-sonnet-4-20250514")
234+
agent_name = workspace_options.get("agent-name", "Example Agent")
235+
```

0 commit comments

Comments
 (0)