How the OpenBB Router Command System Processes Incoming Requests: A Complete Technical Guide
The OpenBB router command system processes incoming HTTP requests through a four-stage pipeline that automatically converts decorated Python functions into FastAPI endpoints, injecting provider dependencies and standard parameters before FastAPI handles the request-response cycle.
The OpenBB router command system serves as the backbone of the OpenBB Platform, transforming data provider functions into fully documented REST API endpoints. Built on top of FastAPI, this system in the OpenBB-finance/OpenBB repository enables automatic endpoint generation through Python decorators, eliminating boilerplate code while maintaining type safety and OpenAPI compliance.
The Four-Stage Processing Pipeline
The OpenBB router command system handles request processing through four distinct architectural stages, each implemented in openbb_platform/core/openbb_core/app/router.py.
Stage 1: Command Registration via the @router.command Decorator
Every data provider function becomes an HTTP endpoint through the @router.command(...) decorator, defined in lines 87-129 of router.py. When applied to a function, this decorator:
- Collects metadata including
model,widget_config, andexamples - Builds the FastAPI route by calling
api_router.add_api_route - Stores the endpoint in the internal
Router._api_routerregistry
The decorator automatically derives the URL path from the function name (defaulting to /{func.__name__}) unless overridden via the path parameter.
Stage 2: Signature Completion and Dependency Injection
Before FastAPI registers the route, the SignatureInspector.complete method (lines 31-84 in router.py) examines and augments the function signature. This stage injects three critical dependency types when a model argument is supplied:
provider_choices→ProviderInterface().model_providers[model]standard_params→ProviderInterface().params[model]["standard"]extra_params→ProviderInterface().params[model]["extra"]
The method also replaces the return annotation with the concrete OBBject subclass matching the specified model, ensuring proper response serialization.
Stage 3: FastAPI Request Handling and Execution
Once the route is registered, FastAPI assumes control of the request lifecycle. When an HTTP request arrives at the defined path:
- FastAPI resolves the
Depends()injections created during signature completion - The framework calls the original provider function with the injected
provider_choices,standard_params, andextra_params - The function returns an
OBBject(or list ofOBBjectinstances) - FastAPI serializes the response using the
response_modelderived from the function's return annotation
This stage requires no manual intervention from the developer, as the OpenBB router command system has already configured all FastAPI-specific parameters during registration.
Stage 4: Routing Hierarchy and Extension Discovery
The system supports nested routing through Router.include_router (lines 73-86 in router.py), which recursively nests Router objects and records them in Router._routers. At application startup, RouterLoader.from_extensions() (lines 18-27) walks through every extension listed in ExtensionLoader().core_objects and constructs the complete route tree.
This hierarchical approach enables the OpenBB router command system to organize endpoints logically (e.g., /equity/price/) while maintaining automatic discovery across all installed extensions.
Practical Implementation: Creating Custom Router Commands
To implement a new endpoint in the OpenBB router command system, developers create a router file within their extension:
# openbb_platform/extensions/equity/openbb_equity/price/price_router.py
from openbb_core.app.router import Router
from openbb_core.app.provider_interface import (
ProviderChoices,
StandardParams,
ExtraParams,
)
from openbb_core.app.model.obbject import OBBject
router = Router(prefix="/price", description="Equity price endpoints")
@router.command(
model="stock",
examples=[{"ticker": "AAPL"}],
widget_config={"height": 400},
)
def get_price(
ticker: str,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject:
"""Return price data for a single ticker."""
return provider_choices.get_price(ticker, standard_params, extra_params)
When the application initializes, RouterLoader processes this module, invokes router.include_router, and registers the endpoint at /price/get_price. The decorator automatically generates the following FastAPI route configuration:
api_router.add_api_route(
path="/get_price",
endpoint=get_price,
methods=["GET"],
response_model=OBBject[PriceResult],
openapi_extra={
"model": "stock",
"widget_config": {"height": 400},
"examples": [{"ticker": "AAPL"}],
},
)
To inspect the complete command mapping at runtime, use the CommandMap utility:
from openbb_core.app.router import CommandMap
cmd_map = CommandMap()
endpoint = cmd_map.get_command("/price/get_price")
print(endpoint) # <function get_price ...>
Key Source Files and Architecture
The OpenBB router command system is implemented across several critical files in the openbb_platform/core/openbb_core/app/ directory:
| File | Role | Key Components |
|---|---|---|
router.py |
Core router implementation | Router class, @command decorator (lines 87-129), SignatureInspector.complete (lines 31-84), Router.include_router (lines 73-86), RouterLoader.from_extensions (lines 18-27) |
provider_interface.py |
Dependency injection interfaces | ProviderChoices, StandardParams, ExtraParams classes |
extension_loader.py |
Extension discovery | ExtensionLoader class that identifies core objects for router registration |
model/obbject.py |
Response modeling | OBBject class used as return type for all commands |
Extension developers implement commands in files following the pattern openbb_platform/extensions/<extension_name>/openbb_<extension_name>/*_router.py, such as openbb_platform/extensions/equity/openbb_equity/price/price_router.py.
Summary
The OpenBB router command system transforms Python functions into HTTP endpoints through a sophisticated four-stage pipeline:
- Registration: The
@router.commanddecorator inrouter.py(lines 87-129) captures metadata and registers routes with FastAPI'sadd_api_route - Signature Completion:
SignatureInspector.complete(lines 31-84) injects provider dependencies (ProviderChoices,StandardParams,ExtraParams) and sets theOBBjectresponse model - Request Handling: FastAPI resolves dependencies, executes the provider function, and serializes the
OBBjectresponse automatically - Hierarchy Management:
RouterLoader.from_extensions(lines 18-27) andinclude_router(lines 73-86) build nested route trees from extension modules
This architecture enables plug-and-play API development where data providers simply decorate functions to expose them as fully documented, dependency-injected endpoints.
Frequently Asked Questions
How does the OpenBB router command system differ from standard FastAPI routing?
Unlike standard FastAPI routing where developers manually define routes using @app.get() or router.add_api_route(), the OpenBB router command system uses a higher-level @router.command decorator that automatically handles dependency injection, response model binding, and OpenAPI metadata generation. The system inspects function signatures and injects provider-specific dependencies (ProviderChoices, StandardParams, ExtraParams) without requiring manual Depends() declarations in the endpoint function.
What is the purpose of the SignatureInspector in the OpenBB router?
The SignatureInspector.complete method, located in openbb_platform/core/openbb_core/app/router.py (lines 31-84), serves as the bridge between provider functions and FastAPI's dependency injection system. It examines the function signature before route registration and automatically injects three critical dependency types when a model is specified: provider_choices for selecting data sources, standard_params for common query parameters, and extra_params for provider-specific options. It also ensures the return type is properly wrapped in an OBBject generic for consistent API responses.
How are provider dependencies injected into router commands?
Provider dependencies are injected through FastAPI's Depends() mechanism, but the OpenBB router command system automates this through the SignatureInspector. When a command is registered with a model parameter (e.g., @router.command(model="stock")), the system looks up the model's requirements in ProviderInterface and injects ProviderChoices, StandardParams, and ExtraParams as hidden dependencies. When a request arrives, FastAPI resolves these dependencies by instantiating the appropriate provider classes and parameter validators before calling the endpoint function.
Can I use the OpenBB router system without the rest of the OpenBB platform?
While the OpenBB router command system is designed as an integral component of the OpenBB Platform, the core routing logic in openbb_platform/core/openbb_core/app/router.py is relatively self-contained and depends primarily on FastAPI. However, to leverage the full automatic dependency injection capabilities (specifically the ProviderChoices, StandardParams, and ExtraParams injections), you would need to implement the ProviderInterface and ExtensionLoader components that define how models map to providers. For basic routing without provider abstraction, standard FastAPI routers would be more appropriate than extracting the OpenBB system.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →