openbb-agent-server 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openbb_agent_server-0.1.0/.gitignore +43 -0
- openbb_agent_server-0.1.0/PKG-INFO +137 -0
- openbb_agent_server-0.1.0/README.md +68 -0
- openbb_agent_server-0.1.0/openbb_agent_server/__init__.py +17 -0
- openbb_agent_server-0.1.0/openbb_agent_server/_vendor/__init__.py +0 -0
- openbb_agent_server-0.1.0/openbb_agent_server/_vendor/sqlitevec.py +135 -0
- openbb_agent_server-0.1.0/openbb_agent_server/acp/__init__.py +32 -0
- openbb_agent_server-0.1.0/openbb_agent_server/acp/canvas.py +1056 -0
- openbb_agent_server-0.1.0/openbb_agent_server/acp/canvas_app.py +480 -0
- openbb_agent_server-0.1.0/openbb_agent_server/acp/provider.py +580 -0
- openbb_agent_server-0.1.0/openbb_agent_server/app/__init__.py +1 -0
- openbb_agent_server-0.1.0/openbb_agent_server/app/app.py +299 -0
- openbb_agent_server-0.1.0/openbb_agent_server/app/config.py +754 -0
- openbb_agent_server-0.1.0/openbb_agent_server/app/router.py +1680 -0
- openbb_agent_server-0.1.0/openbb_agent_server/app/settings.py +779 -0
- openbb_agent_server-0.1.0/openbb_agent_server/main.py +396 -0
- openbb_agent_server-0.1.0/openbb_agent_server/memory/__init__.py +1 -0
- openbb_agent_server-0.1.0/openbb_agent_server/memory/classifier.py +201 -0
- openbb_agent_server-0.1.0/openbb_agent_server/memory/embeddings.py +118 -0
- openbb_agent_server-0.1.0/openbb_agent_server/memory/factory.py +226 -0
- openbb_agent_server-0.1.0/openbb_agent_server/memory/ingestion.py +424 -0
- openbb_agent_server-0.1.0/openbb_agent_server/memory/reranker.py +165 -0
- openbb_agent_server-0.1.0/openbb_agent_server/memory/retrievers.py +177 -0
- openbb_agent_server-0.1.0/openbb_agent_server/memory/sqlite_store.py +593 -0
- openbb_agent_server-0.1.0/openbb_agent_server/memory/store.py +196 -0
- openbb_agent_server-0.1.0/openbb_agent_server/memory/translation.py +161 -0
- openbb_agent_server-0.1.0/openbb_agent_server/memory/writer.py +163 -0
- openbb_agent_server-0.1.0/openbb_agent_server/observability/__init__.py +1 -0
- openbb_agent_server-0.1.0/openbb_agent_server/observability/logging.py +272 -0
- openbb_agent_server-0.1.0/openbb_agent_server/openbb.toml.example +332 -0
- openbb_agent_server-0.1.0/openbb_agent_server/persistence/__init__.py +1 -0
- openbb_agent_server-0.1.0/openbb_agent_server/persistence/models.py +650 -0
- openbb_agent_server-0.1.0/openbb_agent_server/persistence/prune.py +297 -0
- openbb_agent_server-0.1.0/openbb_agent_server/persistence/sqlite_store.py +857 -0
- openbb_agent_server-0.1.0/openbb_agent_server/persistence/store.py +444 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/__init__.py +1 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/auth/__init__.py +1 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/auth/api_key_table.py +303 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/auth/bearer_static.py +107 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/auth/none.py +60 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/auth/oidc_jwt.py +138 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/auth/openbb_workspace.py +111 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/checkpointers/__init__.py +1 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/checkpointers/inmemory.py +61 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/checkpointers/postgres.py +148 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/checkpointers/sqlite.py +109 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/middleware/__init__.py +1 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/middleware/call_limit.py +143 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/middleware/loop_guard.py +152 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/middleware/tool_call_announcer.py +120 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/middleware/tool_call_ledger.py +147 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/middleware/tool_filter.py +117 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/middleware/tool_message_normaliser.py +336 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/middleware/usage_recorder.py +95 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/models/__init__.py +1 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/models/_validation.py +55 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/models/anthropic_provider.py +158 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/models/bedrock_provider.py +182 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/models/fake_provider.py +138 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/models/google_genai_provider.py +226 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/models/groq_provider.py +248 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/models/groq_rate_limiter.py +447 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/models/nvidia_provider.py +241 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/models/openai_compat_provider.py +266 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/models/openai_provider.py +198 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/models/vertex_provider.py +221 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/subagents/__init__.py +1 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/subagents/analyst.py +50 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/subagents/charter.py +51 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/subagents/pdf_reader.py +57 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/subagents/researcher.py +69 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/__init__.py +1 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/_media.py +470 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/artifacts.py +328 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/background_jobs.py +158 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/client_side.py +115 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/dashboard.py +108 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/fetch_url.py +294 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/gemini_embeddings.py +230 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/gemini_image.py +621 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/gemma_audio.py +461 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/groq_audio.py +404 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/inspect_widget_data.py +389 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/mcp_http.py +230 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/mcp_local.py +194 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/memory_recall.py +95 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/paligemma_vision.py +468 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/pdf_extract.py +1089 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/python_module.py +93 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/pywry_canvas.py +1730 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/rerank.py +160 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/translate.py +138 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/vision_qa.py +380 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/web_search.py +177 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/widget_data.py +194 -0
- openbb_agent_server-0.1.0/openbb_agent_server/plugins/tools/workspace_mcp.py +84 -0
- openbb_agent_server-0.1.0/openbb_agent_server/prompts/__init__.py +12 -0
- openbb_agent_server-0.1.0/openbb_agent_server/prompts/default_system_prompt.md +412 -0
- openbb_agent_server-0.1.0/openbb_agent_server/protocol/__init__.py +1 -0
- openbb_agent_server-0.1.0/openbb_agent_server/protocol/adapter.py +771 -0
- openbb_agent_server-0.1.0/openbb_agent_server/protocol/schemas.py +556 -0
- openbb_agent_server-0.1.0/openbb_agent_server/protocol/sse.py +60 -0
- openbb_agent_server-0.1.0/openbb_agent_server/py.typed +0 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/__init__.py +1 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/builder.py +987 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/canvas.py +234 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/context.py +216 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/embedded.py +384 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/emit.py +568 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/identity.py +118 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/jobs.py +386 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/pdf_store.py +715 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/plugins.py +190 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/principal.py +54 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/registry.py +107 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/services.py +169 -0
- openbb_agent_server-0.1.0/openbb_agent_server/runtime/widget_store.py +707 -0
- openbb_agent_server-0.1.0/pyproject.toml +228 -0
- openbb_agent_server-0.1.0/website/README.md +37 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# --- Python ---
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
.venv/
|
|
5
|
+
*.egg-info/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
.coverage
|
|
9
|
+
.coverage.*
|
|
10
|
+
coverage.xml
|
|
11
|
+
htmlcov/
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.ruff_cache/
|
|
14
|
+
.ty_cache/
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
|
|
17
|
+
# --- Docs site (Docusaurus, in ./website) ---
|
|
18
|
+
node_modules/
|
|
19
|
+
website/build/
|
|
20
|
+
website/.docusaurus/
|
|
21
|
+
website/.cache-loader/
|
|
22
|
+
npm-debug.log*
|
|
23
|
+
yarn-error.log*
|
|
24
|
+
|
|
25
|
+
# Auto-generated API reference: rebuilt from the package docstrings by
|
|
26
|
+
# ``npm run gen-api`` (wiped + regenerated on every run, never
|
|
27
|
+
# hand-edited). The deploy workflow regenerates it in CI, so it is not
|
|
28
|
+
# tracked here.
|
|
29
|
+
/docs/reference/
|
|
30
|
+
|
|
31
|
+
# --- Secrets / local environment ---
|
|
32
|
+
.env
|
|
33
|
+
.env.*
|
|
34
|
+
!.env.example
|
|
35
|
+
|
|
36
|
+
# --- Editors / OS ---
|
|
37
|
+
.vscode/
|
|
38
|
+
.idea/
|
|
39
|
+
.DS_Store
|
|
40
|
+
Thumbs.db
|
|
41
|
+
|
|
42
|
+
# --- Local agent tooling ---
|
|
43
|
+
.claude/
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openbb-agent-server
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: OpenBB Agent Server: pluggable, multi-tenant agent backend wired to the OpenBB Workspace UI.
|
|
5
|
+
Project-URL: Homepage, https://github.com/deeleeramone/openbb-agent-server
|
|
6
|
+
Project-URL: Repository, https://github.com/deeleeramone/openbb-agent-server
|
|
7
|
+
Author-email: Danglewood <85772166+deeleeramone@users.noreply.github.com>
|
|
8
|
+
License: AGPL-3.0-only
|
|
9
|
+
Requires-Python: <4,>=3.11
|
|
10
|
+
Requires-Dist: aiosqlite>=0.20
|
|
11
|
+
Requires-Dist: alembic>=1.13
|
|
12
|
+
Requires-Dist: argon2-cffi>=23.1
|
|
13
|
+
Requires-Dist: ddgs>=9.0
|
|
14
|
+
Requires-Dist: deepagents>=0.5.0
|
|
15
|
+
Requires-Dist: fastapi>=0.115.0
|
|
16
|
+
Requires-Dist: fastmcp>=3.2.0
|
|
17
|
+
Requires-Dist: httpx2>=0.1
|
|
18
|
+
Requires-Dist: langchain-core>=1.0.0
|
|
19
|
+
Requires-Dist: langchain-mcp-adapters>=0.2.0
|
|
20
|
+
Requires-Dist: langchain-nvidia-ai-endpoints>=1.0.0
|
|
21
|
+
Requires-Dist: langchain-text-splitters>=0.3
|
|
22
|
+
Requires-Dist: langchain>=1.0.0
|
|
23
|
+
Requires-Dist: langgraph-checkpoint-sqlite>=2.0
|
|
24
|
+
Requires-Dist: langgraph>=1.0.0
|
|
25
|
+
Requires-Dist: pdfplumber>=0.11
|
|
26
|
+
Requires-Dist: pydantic-settings>=2.5
|
|
27
|
+
Requires-Dist: pydantic<3,>=2.7
|
|
28
|
+
Requires-Dist: pyjwt[crypto]>=2.9
|
|
29
|
+
Requires-Dist: python-dotenv>=1.0
|
|
30
|
+
Requires-Dist: sqlalchemy[asyncio]<3,>=2.0
|
|
31
|
+
Requires-Dist: sqlite-vec>=0.1.6
|
|
32
|
+
Requires-Dist: sse-starlette>=2.1.0
|
|
33
|
+
Requires-Dist: uuid7>=0.1
|
|
34
|
+
Requires-Dist: uvicorn>=0.32.0
|
|
35
|
+
Provides-Extra: all
|
|
36
|
+
Requires-Dist: google-genai>=1.0.0; extra == 'all'
|
|
37
|
+
Requires-Dist: langchain-anthropic>=1.0.0; extra == 'all'
|
|
38
|
+
Requires-Dist: langchain-aws>=0.2.0; extra == 'all'
|
|
39
|
+
Requires-Dist: langchain-google-genai>=2.0.0; extra == 'all'
|
|
40
|
+
Requires-Dist: langchain-groq>=0.2.0; extra == 'all'
|
|
41
|
+
Requires-Dist: langchain-openai>=0.2.0; extra == 'all'
|
|
42
|
+
Requires-Dist: langgraph-checkpoint-postgres>=2.0; extra == 'all'
|
|
43
|
+
Requires-Dist: pgvector>=0.3; extra == 'all'
|
|
44
|
+
Requires-Dist: psycopg[binary]>=3.2; extra == 'all'
|
|
45
|
+
Requires-Dist: tavily-python>=0.5; extra == 'all'
|
|
46
|
+
Provides-Extra: anthropic
|
|
47
|
+
Requires-Dist: langchain-anthropic>=1.0.0; extra == 'anthropic'
|
|
48
|
+
Provides-Extra: bedrock
|
|
49
|
+
Requires-Dist: langchain-aws>=0.2.0; extra == 'bedrock'
|
|
50
|
+
Provides-Extra: google-genai
|
|
51
|
+
Requires-Dist: google-genai>=1.0.0; extra == 'google-genai'
|
|
52
|
+
Requires-Dist: langchain-google-genai>=2.0.0; extra == 'google-genai'
|
|
53
|
+
Provides-Extra: groq
|
|
54
|
+
Requires-Dist: langchain-groq>=0.2.0; extra == 'groq'
|
|
55
|
+
Provides-Extra: openai
|
|
56
|
+
Requires-Dist: langchain-openai>=0.2.0; extra == 'openai'
|
|
57
|
+
Provides-Extra: postgres
|
|
58
|
+
Requires-Dist: langgraph-checkpoint-postgres>=2.0; extra == 'postgres'
|
|
59
|
+
Requires-Dist: pgvector>=0.3; extra == 'postgres'
|
|
60
|
+
Requires-Dist: psycopg[binary]>=3.2; extra == 'postgres'
|
|
61
|
+
Provides-Extra: pywry
|
|
62
|
+
Requires-Dist: pywry>=2.0.4; extra == 'pywry'
|
|
63
|
+
Provides-Extra: tavily
|
|
64
|
+
Requires-Dist: tavily-python>=0.5; extra == 'tavily'
|
|
65
|
+
Provides-Extra: vertex
|
|
66
|
+
Requires-Dist: google-genai>=1.0.0; extra == 'vertex'
|
|
67
|
+
Requires-Dist: langchain-google-genai>=2.0.0; extra == 'vertex'
|
|
68
|
+
Description-Content-Type: text/markdown
|
|
69
|
+
|
|
70
|
+
# openbb-agent-server
|
|
71
|
+
|
|
72
|
+
Pluggable, multi-tenant agent backend that speaks the [OpenBB Workspace
|
|
73
|
+
custom-agent SSE protocol](https://docs.openbb.co/workspace/developers/agents-integration) and runs the agent loop
|
|
74
|
+
on top of the [LangChain DeepAgents harness](https://docs.langchain.com/oss/python/deepagents/overview). One process
|
|
75
|
+
hosts many agent profiles; auth, model provider, tools, sub-agents,
|
|
76
|
+
middleware, checkpointer, and persistence are independent plugin axes
|
|
77
|
+
— anything can be swapped without forking the package.
|
|
78
|
+
|
|
79
|
+
<img width="1580" height="834" alt="openbb-agent-server-screenshot" src="https://github.com/user-attachments/assets/f6ed834a-4232-4cbb-a039-275f30dafad9" />
|
|
80
|
+
|
|
81
|
+
The full OpenBB Platform — every command across every installed
|
|
82
|
+
provider — is reachable via the optional `mcp_local` tool source,
|
|
83
|
+
which spawns the
|
|
84
|
+
[`openbb-mcp-server`](https://github.com/OpenBB-finance/OpenBB/tree/main/openbb_platform/extensions/mcp_server)
|
|
85
|
+
extension over stdio.
|
|
86
|
+
|
|
87
|
+
The default setup uses 100% free tokens and embedding models available from [NVIDIA](https://build.nvidia.com/) by registering for an API key [here](https://developer.nvidia.com/login)
|
|
88
|
+
|
|
89
|
+
## Install & run
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# from PyPI
|
|
93
|
+
pip install openbb-agent-server
|
|
94
|
+
|
|
95
|
+
# from a checkout of this repository
|
|
96
|
+
pip install -e '.[workspace-mcp]'
|
|
97
|
+
# add or combine more extras: [anthropic] [openai] [bedrock]
|
|
98
|
+
# [vertex] [google_genai] [groq]
|
|
99
|
+
# [tavily] [postgres]
|
|
100
|
+
# [pywry] (desktop chat embedding)
|
|
101
|
+
|
|
102
|
+
export NVIDIA_API_KEY=...
|
|
103
|
+
|
|
104
|
+
openbb-agent-server
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
In OpenBB Workspace, add a custom agent pointing at
|
|
108
|
+
`http://localhost:8010`. Workspace fetches this once and
|
|
109
|
+
reads every agent profile the server registers in a single payload.
|
|
110
|
+
|
|
111
|
+
The `[workspace-mcp]` extra installs
|
|
112
|
+
[openbb-workspace-mcp](https://github.com/OpenBB-finance/workspace-mcp)
|
|
113
|
+
from its GitHub zip (Python ≥3.13 only). To run it in-process and skip
|
|
114
|
+
the separate `workspace-mcp` sidecar, set `mount_workspace_mcp = true`
|
|
115
|
+
in `openbb.toml` after installing the extra, then point the Workspace
|
|
116
|
+
UI's MCP-servers setting at `http://localhost:8010/mcp/workspace/mcp`.
|
|
117
|
+
The mount is **opt-in** (default `false`) so installing the extra alone
|
|
118
|
+
does not change the server's behavior.
|
|
119
|
+
|
|
120
|
+
For production, generate the config template and edit it:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
openbb-agent-server --generate-config /etc/openbb/openbb.toml
|
|
124
|
+
openbb-agent-server --config-file /etc/openbb/openbb.toml --host 0.0.0.0
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Documentation
|
|
128
|
+
|
|
129
|
+
Documentation currently lives in [`docs/`](docs/README.md), and may move in the future:
|
|
130
|
+
|
|
131
|
+
| Audience | Start here |
|
|
132
|
+
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
133
|
+
| First-time user | [Getting started](docs/guides/getting-started.md) → [Architecture](docs/guides/architecture.md) → [Workspace integration](docs/guides/workspace-integration.md) |
|
|
134
|
+
| Desktop embedding | [PyWry chat (ACP)](docs/guides/pywry-chat.md) — `openbb-agent-canvas` opens a window whose main page is the agent's live canvas (charts, tables, HTML) with the chat attached; or attach the chat to any PyWry widget via the `[pywry]` extra. Same `openbb.toml`, same loop, no HTTP server |
|
|
135
|
+
| Operator / SRE | [Configuration](docs/operating/configuration.md) → [Auth](docs/operating/auth.md) → [Persistence](docs/operating/persistence.md) → [Observability](docs/operating/observability.md) |
|
|
136
|
+
| Plugin author | [Plugin system](docs/developing/plugin-system.md) → writing a [tool source](docs/developing/writing-a-tool-source.md) / [model provider](docs/developing/writing-a-model-provider.md) / [middleware](docs/developing/writing-a-middleware.md) / [sub-agent](docs/developing/writing-a-subagent.md) / [auth backend](docs/developing/writing-an-auth-backend.md) → [Conventions](docs/developing/conventions.md) → [Testing](docs/developing/testing.md) |
|
|
137
|
+
| API lookup | [Reference](docs/reference/) — module-by-module, mirrors the package tree |
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# openbb-agent-server
|
|
2
|
+
|
|
3
|
+
Pluggable, multi-tenant agent backend that speaks the [OpenBB Workspace
|
|
4
|
+
custom-agent SSE protocol](https://docs.openbb.co/workspace/developers/agents-integration) and runs the agent loop
|
|
5
|
+
on top of the [LangChain DeepAgents harness](https://docs.langchain.com/oss/python/deepagents/overview). One process
|
|
6
|
+
hosts many agent profiles; auth, model provider, tools, sub-agents,
|
|
7
|
+
middleware, checkpointer, and persistence are independent plugin axes
|
|
8
|
+
— anything can be swapped without forking the package.
|
|
9
|
+
|
|
10
|
+
<img width="1580" height="834" alt="openbb-agent-server-screenshot" src="https://github.com/user-attachments/assets/f6ed834a-4232-4cbb-a039-275f30dafad9" />
|
|
11
|
+
|
|
12
|
+
The full OpenBB Platform — every command across every installed
|
|
13
|
+
provider — is reachable via the optional `mcp_local` tool source,
|
|
14
|
+
which spawns the
|
|
15
|
+
[`openbb-mcp-server`](https://github.com/OpenBB-finance/OpenBB/tree/main/openbb_platform/extensions/mcp_server)
|
|
16
|
+
extension over stdio.
|
|
17
|
+
|
|
18
|
+
The default setup uses 100% free tokens and embedding models available from [NVIDIA](https://build.nvidia.com/) by registering for an API key [here](https://developer.nvidia.com/login)
|
|
19
|
+
|
|
20
|
+
## Install & run
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# from PyPI
|
|
24
|
+
pip install openbb-agent-server
|
|
25
|
+
|
|
26
|
+
# from a checkout of this repository
|
|
27
|
+
pip install -e '.[workspace-mcp]'
|
|
28
|
+
# add or combine more extras: [anthropic] [openai] [bedrock]
|
|
29
|
+
# [vertex] [google_genai] [groq]
|
|
30
|
+
# [tavily] [postgres]
|
|
31
|
+
# [pywry] (desktop chat embedding)
|
|
32
|
+
|
|
33
|
+
export NVIDIA_API_KEY=...
|
|
34
|
+
|
|
35
|
+
openbb-agent-server
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
In OpenBB Workspace, add a custom agent pointing at
|
|
39
|
+
`http://localhost:8010`. Workspace fetches this once and
|
|
40
|
+
reads every agent profile the server registers in a single payload.
|
|
41
|
+
|
|
42
|
+
The `[workspace-mcp]` extra installs
|
|
43
|
+
[openbb-workspace-mcp](https://github.com/OpenBB-finance/workspace-mcp)
|
|
44
|
+
from its GitHub zip (Python ≥3.13 only). To run it in-process and skip
|
|
45
|
+
the separate `workspace-mcp` sidecar, set `mount_workspace_mcp = true`
|
|
46
|
+
in `openbb.toml` after installing the extra, then point the Workspace
|
|
47
|
+
UI's MCP-servers setting at `http://localhost:8010/mcp/workspace/mcp`.
|
|
48
|
+
The mount is **opt-in** (default `false`) so installing the extra alone
|
|
49
|
+
does not change the server's behavior.
|
|
50
|
+
|
|
51
|
+
For production, generate the config template and edit it:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
openbb-agent-server --generate-config /etc/openbb/openbb.toml
|
|
55
|
+
openbb-agent-server --config-file /etc/openbb/openbb.toml --host 0.0.0.0
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Documentation
|
|
59
|
+
|
|
60
|
+
Documentation currently lives in [`docs/`](docs/README.md), and may move in the future:
|
|
61
|
+
|
|
62
|
+
| Audience | Start here |
|
|
63
|
+
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
64
|
+
| First-time user | [Getting started](docs/guides/getting-started.md) → [Architecture](docs/guides/architecture.md) → [Workspace integration](docs/guides/workspace-integration.md) |
|
|
65
|
+
| Desktop embedding | [PyWry chat (ACP)](docs/guides/pywry-chat.md) — `openbb-agent-canvas` opens a window whose main page is the agent's live canvas (charts, tables, HTML) with the chat attached; or attach the chat to any PyWry widget via the `[pywry]` extra. Same `openbb.toml`, same loop, no HTTP server |
|
|
66
|
+
| Operator / SRE | [Configuration](docs/operating/configuration.md) → [Auth](docs/operating/auth.md) → [Persistence](docs/operating/persistence.md) → [Observability](docs/operating/observability.md) |
|
|
67
|
+
| Plugin author | [Plugin system](docs/developing/plugin-system.md) → writing a [tool source](docs/developing/writing-a-tool-source.md) / [model provider](docs/developing/writing-a-model-provider.md) / [middleware](docs/developing/writing-a-middleware.md) / [sub-agent](docs/developing/writing-a-subagent.md) / [auth backend](docs/developing/writing-an-auth-backend.md) → [Conventions](docs/developing/conventions.md) → [Testing](docs/developing/testing.md) |
|
|
68
|
+
| API lookup | [Reference](docs/reference/) — module-by-module, mirrors the package tree |
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""OpenBB Platform Agent Server — pluggable, multi-tenant agent backend."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import warnings
|
|
6
|
+
|
|
7
|
+
__version__ = "0.1.0"
|
|
8
|
+
|
|
9
|
+
from langchain_core._api.deprecation import ( # noqa: E402
|
|
10
|
+
LangChainPendingDeprecationWarning,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
warnings.filterwarnings(
|
|
14
|
+
"ignore",
|
|
15
|
+
message=r"The default value of `allowed_objects` will change.*",
|
|
16
|
+
category=LangChainPendingDeprecationWarning,
|
|
17
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Vendored SQLiteVec vector store.
|
|
2
|
+
|
|
3
|
+
Adapted from ``langchain_community.vectorstores.sqlitevec`` (MIT licence)
|
|
4
|
+
to remove the ``langchain-community`` dependency, which is now archived.
|
|
5
|
+
|
|
6
|
+
Only the surface used by this project is kept:
|
|
7
|
+
|
|
8
|
+
* ``create_table_if_not_exists``
|
|
9
|
+
* ``add_texts``
|
|
10
|
+
* ``similarity_search_with_score``
|
|
11
|
+
|
|
12
|
+
The class intentionally does **not** manage connection lifecycle — the
|
|
13
|
+
caller is responsible for opening and closing the ``sqlite3.Connection``.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
import sqlite3
|
|
20
|
+
import struct
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
from langchain_core.documents import Document
|
|
24
|
+
from langchain_core.embeddings import Embeddings
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _serialize_f32(vector: list[float]) -> bytes:
|
|
28
|
+
"""Pack a float vector into the raw-bytes format sqlite-vec expects."""
|
|
29
|
+
return struct.pack(f"{len(vector)}f", *vector)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class SQLiteVec:
|
|
33
|
+
"""Thin wrapper around a ``sqlite-vec`` virtual table.
|
|
34
|
+
|
|
35
|
+
Requires a pre-configured ``sqlite3.Connection`` with the ``sqlite-vec``
|
|
36
|
+
extension already loaded.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(
|
|
40
|
+
self,
|
|
41
|
+
table: str,
|
|
42
|
+
connection: sqlite3.Connection,
|
|
43
|
+
embedding: Embeddings,
|
|
44
|
+
db_file: str = "vec.db",
|
|
45
|
+
) -> None:
|
|
46
|
+
self._connection = connection
|
|
47
|
+
self._table = table
|
|
48
|
+
self._embedding = embedding
|
|
49
|
+
|
|
50
|
+
# ------------------------------------------------------------------
|
|
51
|
+
# Schema helpers
|
|
52
|
+
# ------------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
def create_table_if_not_exists(self) -> None:
|
|
55
|
+
"""Create the data table, vec0 virtual table, and insert trigger."""
|
|
56
|
+
dim = len(self._embedding.embed_query("dim probe"))
|
|
57
|
+
self._connection.execute(
|
|
58
|
+
f"CREATE TABLE IF NOT EXISTS {self._table}"
|
|
59
|
+
" (rowid INTEGER PRIMARY KEY AUTOINCREMENT,"
|
|
60
|
+
" text TEXT, metadata BLOB, text_embedding BLOB)"
|
|
61
|
+
)
|
|
62
|
+
self._connection.execute(
|
|
63
|
+
f"CREATE VIRTUAL TABLE IF NOT EXISTS {self._table}_vec"
|
|
64
|
+
f" USING vec0(rowid INTEGER PRIMARY KEY,"
|
|
65
|
+
f" text_embedding float[{dim}])"
|
|
66
|
+
)
|
|
67
|
+
self._connection.execute(
|
|
68
|
+
f"CREATE TRIGGER IF NOT EXISTS {self._table}_embed_text "
|
|
69
|
+
f"AFTER INSERT ON {self._table} BEGIN"
|
|
70
|
+
f" INSERT INTO {self._table}_vec(rowid, text_embedding)"
|
|
71
|
+
f" VALUES (new.rowid, new.text_embedding); END;"
|
|
72
|
+
)
|
|
73
|
+
self._connection.commit()
|
|
74
|
+
|
|
75
|
+
# ------------------------------------------------------------------
|
|
76
|
+
# Write
|
|
77
|
+
# ------------------------------------------------------------------
|
|
78
|
+
|
|
79
|
+
def add_texts(
|
|
80
|
+
self,
|
|
81
|
+
texts: list[str],
|
|
82
|
+
metadatas: list[dict[str, Any]],
|
|
83
|
+
**kwargs: Any,
|
|
84
|
+
) -> list[int]:
|
|
85
|
+
"""Embed *texts* and insert them into the store.
|
|
86
|
+
|
|
87
|
+
Returns the ``rowid`` values of the newly inserted rows.
|
|
88
|
+
"""
|
|
89
|
+
row = self._connection.execute(
|
|
90
|
+
f"SELECT max(rowid) AS rowid FROM {self._table}"
|
|
91
|
+
).fetchone()
|
|
92
|
+
max_id: int = row["rowid"] if row["rowid"] is not None else 0
|
|
93
|
+
|
|
94
|
+
embeds = self._embedding.embed_documents(list(texts))
|
|
95
|
+
|
|
96
|
+
self._connection.executemany(
|
|
97
|
+
f"INSERT INTO {self._table}(text, metadata, text_embedding)"
|
|
98
|
+
" VALUES (?, ?, ?)",
|
|
99
|
+
[
|
|
100
|
+
(text, json.dumps(meta), _serialize_f32(emb))
|
|
101
|
+
for text, meta, emb in zip(texts, metadatas, embeds)
|
|
102
|
+
],
|
|
103
|
+
)
|
|
104
|
+
self._connection.commit()
|
|
105
|
+
|
|
106
|
+
rows = self._connection.execute(
|
|
107
|
+
f"SELECT rowid FROM {self._table} WHERE rowid > {max_id}"
|
|
108
|
+
)
|
|
109
|
+
return [r["rowid"] for r in rows]
|
|
110
|
+
|
|
111
|
+
# ------------------------------------------------------------------
|
|
112
|
+
# Read
|
|
113
|
+
# ------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
def similarity_search_with_score(
|
|
116
|
+
self, query: str, k: int = 4, **kwargs: Any
|
|
117
|
+
) -> list[tuple[Document, float]]:
|
|
118
|
+
"""Return the *k* closest documents with their distance scores."""
|
|
119
|
+
embedding = self._embedding.embed_query(query)
|
|
120
|
+
cursor = self._connection.cursor()
|
|
121
|
+
cursor.execute(
|
|
122
|
+
f"SELECT text, metadata, distance"
|
|
123
|
+
f" FROM {self._table} AS e"
|
|
124
|
+
f" INNER JOIN {self._table}_vec AS v ON v.rowid = e.rowid"
|
|
125
|
+
f" WHERE v.text_embedding MATCH ? AND k = ?"
|
|
126
|
+
f" ORDER BY distance",
|
|
127
|
+
[_serialize_f32(embedding), k],
|
|
128
|
+
)
|
|
129
|
+
results: list[tuple[Document, float]] = []
|
|
130
|
+
for row in cursor.fetchall():
|
|
131
|
+
meta = json.loads(row["metadata"]) if row["metadata"] else {}
|
|
132
|
+
results.append(
|
|
133
|
+
(Document(page_content=row["text"], metadata=meta), row["distance"])
|
|
134
|
+
)
|
|
135
|
+
return results
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""ACP shim — expose the agent loop to PyWry chat components.
|
|
2
|
+
|
|
3
|
+
Lazy re-exports so ``import openbb_agent_server.acp`` works without
|
|
4
|
+
pywry installed; the ImportError with install instructions surfaces on
|
|
5
|
+
first attribute access instead. ``PyWryCanvas`` / ``build_canvas_html``
|
|
6
|
+
are pywry-free and always importable.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from importlib import import_module
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
_EXPORTS: dict[str, str] = {
|
|
15
|
+
"OpenBBAgentProvider": "openbb_agent_server.acp.provider",
|
|
16
|
+
"create_chat_manager": "openbb_agent_server.acp.provider",
|
|
17
|
+
"translate_sse": "openbb_agent_server.acp.provider",
|
|
18
|
+
"launch": "openbb_agent_server.acp.canvas_app",
|
|
19
|
+
"CanvasApp": "openbb_agent_server.acp.canvas_app",
|
|
20
|
+
"PyWryCanvas": "openbb_agent_server.acp.canvas",
|
|
21
|
+
"build_canvas_html": "openbb_agent_server.acp.canvas",
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
__all__ = list(_EXPORTS)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def __getattr__(name: str) -> Any:
|
|
28
|
+
"""Defer submodule imports until a symbol is actually used."""
|
|
29
|
+
module_path = _EXPORTS.get(name)
|
|
30
|
+
if module_path is None:
|
|
31
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
32
|
+
return getattr(import_module(module_path), name)
|