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, and examples
  • Builds the FastAPI route by calling api_router.add_api_route
  • Stores the endpoint in the internal Router._api_router registry

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:

  1. FastAPI resolves the Depends() injections created during signature completion
  2. The framework calls the original provider function with the injected provider_choices, standard_params, and extra_params
  3. The function returns an OBBject (or list of OBBject instances)
  4. FastAPI serializes the response using the response_model derived 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.command decorator in router.py (lines 87-129) captures metadata and registers routes with FastAPI's add_api_route
  • Signature Completion: SignatureInspector.complete (lines 31-84) injects provider dependencies (ProviderChoices, StandardParams, ExtraParams) and sets the OBBject response model
  • Request Handling: FastAPI resolves dependencies, executes the provider function, and serializes the OBBject response automatically
  • Hierarchy Management: RouterLoader.from_extensions (lines 18-27) and include_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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →