Skip to main content

FigureOut - a lightweight and resilient multi-LLM orchestrator

PyPI version License PyPI Downloads

FigureOut is a lightweight, modular orchestrator for developers who want to build LLM workflows without the framework bloat. Unlike heavy frameworks that hide logic behind abstractions, FigureOut keeps your code clean, predictable, and easy to debug. Perfect for prototyping and production-grade apps where you need full control.

The package classifies incoming queries and dispatches them to the appropriate role, returning a structured JSON response.

Installation

Install the base package plus the extra for your LLM provider:

pip install figureout[openai]   # OpenAI
pip install figureout[gemini]   # Google Gemini
pip install figureout[claude]   # Anthropic Claude
pip install figureout[meta]     # Meta (Llama)
pip install figureout[mistral]  # Mistral
pip install figureout[groq]     # Groq
pip install figureout[all]      # All providers

Supported LLM Providers

Provider Enum API Key Env Var Install Extra
OpenAI LLM.OPENAI OPENAI_API_KEY pip install figureout[openai]
Google Gemini LLM.GEMINI GEMINI_API_KEY pip install figureout[gemini]
Anthropic Claude LLM.CLAUDE ANTHROPIC_API_KEY pip install figureout[claude]
Meta (Llama) LLM.META META_API_KEY pip install figureout[meta]
Mistral LLM.MISTRAL MISTRAL_API_KEY pip install figureout[mistral]
Groq LLM.GROQ GROQ_API_KEY pip install figureout[groq]

Only install the extra for the provider(s) you intend to use.

Quick Start

import asyncio
from figureout import FigureOut, RoleDefinition

concierge = FigureOut(
    llm="openai",
    llm_version="gpt-4o",
    roles={
        "product_search": RoleDefinition(
            prompt="You are a product search specialist. Help users find products.",
            schema='{"results": [{"id": int, "name": str, "price": float}], "summary": str}',
            guideline="queries about finding or searching for products",
        ),
        "off_topic": RoleDefinition(
            prompt="Politely decline and explain you can only help with product searches.",
            schema='{"message": str}',
            guideline="anything unrelated to products",
        ),
    },
)

result = asyncio.run(concierge.run("Find me a blue running shoe under $100"))
print(result)
# {"results": [...], "summary": "..."}

API

FigureOut Constructor

FigureOut(
    llm: str | LLM,
    llm_version: str,
    roles: dict[str, RoleDefinition],
    lite_llm_version: str | None = None,
    verbose: bool = False,
    max_roles: int = 1,
    max_output_tokens: int = 16384,
    max_retries: int = 2,
    max_tool_rounds: int = 3,
    interpret_tool_response: bool | None = None,
    cache_enabled: bool = True,
    cache_size: int = 128,
    inject_date: bool = True,
    api_key: str | None = None,
    mcp_server=None,
)

All constructor params can also be set via environment variables:

Param Env Var
llm FIGUREOUT_LLM
llm_version FIGUREOUT_LLM_VERSION
lite_llm_version FIGUREOUT_LITE_LLM_VERSION
verbose FIGUREOUT_VERBOSE
max_roles FIGUREOUT_MAX_ROLES
max_output_tokens FIGUREOUT_MAX_OUTPUT_TOKENS
max_retries FIGUREOUT_MAX_RETRIES
max_tool_rounds FIGUREOUT_MAX_TOOL_ROUNDS
interpret_tool_response FIGUREOUT_INTERPRET_TOOL_RESPONSE
cache_enabled FIGUREOUT_CACHE_ENABLED
cache_size FIGUREOUT_CACHE_SIZE
inject_date FIGUREOUT_INJECT_DATE

RoleDefinition

RoleDefinition(
    prompt: str,      # System prompt for this role
    schema: str,      # JSON schema string defining the output shape
    guideline: str,   # Short description used by the classifier to select this role
)

run() Method

await concierge.run(
    user_query: str,
    role: str | None = None,         # Skip classification, use this role directly
    context: str | None = None,      # Prepended to user_query as additional context
    output_schema: str | None = None # Override the role's default schema
)

Returns a dict matching the role's output schema.

Multi-Role Queries

Set max_roles > 1 to allow multiple roles to handle a single query in parallel:

concierge = FigureOut(llm="openai", llm_version="gpt-4o", roles=ROLES, max_roles=3)
result = await concierge.run("Find concerts and sports events this weekend")
# {"concert_discovery": {...}, "sports_discovery": {...}}

When a single role is selected, the result is returned directly (not wrapped in a role-keyed dict).

off_topic Role

Define an "off_topic" role to control fallback behavior. The classifier never selects it directly — it is used automatically when no other role matches:

"off_topic": RoleDefinition(
    prompt="Politely decline.",
    schema='{"message": str}',
    guideline="anything unrelated",
)

Tool Use (FastMCP)

Pass a FastMCP server to enable tool calling:

from fastmcp import FastMCP

mcp = FastMCP("my-server")

@mcp.tool()
def search_products(query: str) -> list:
    ...

concierge = FigureOut(llm="gemini", llm_version="gemini-2.0-flash", roles=ROLES, mcp_server=mcp)

interpret_tool_response

Controls how tool results are handled after tool execution:

Value Behavior
None (default) Normal loop — LLM responds naturally after tool calls
True Bridge messages appended after tool calls + forced JSON mode round; ensures nested fields are populated
False Return raw tool output without sending back to the LLM

Use interpret_tool_response=True for roles that return complex nested JSON structures.

Verbose Mode

With verbose=True, the response is wrapped under a "response" key and a "debug" key is added with token usage and timing information:

concierge = FigureOut(..., verbose=True)
result = await concierge.run("Find flights to Tokyo")
# {"response": {"flights": [...]}, "debug": {"input_tokens": 512, "output_tokens": 256,
#   "classifier_input_tokens": 180, "classifier_output_tokens": 8, ...}}

input_tokens and output_tokens are totals for the whole call, including the role-classification call. classifier_input_tokens and classifier_output_tokens give the classification share on its own; both are 0 when role= is passed explicitly.

Examples

The examples/ directory contains complete domain-specific backends with React+Vite frontends:

Example Domain
event-sports-booking/ Sports event discovery and booking
flight-booking/ Flight search and booking
restaurant-reservation/ Restaurant discovery and reservations
things-to-do/ Activity and places discovery
customer-support-chat/ FAQ-based customer support chat

To run an example:

cd examples/<example-name>/mcp-server
python app.py

Development

pip install -e ".[dev]"
pytest
pytest tests/test_figureout.py::test_name  # Run a single test

Metadata

Release files for figureout 0.2.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for figureout 0.2.4
File Size Uploaded Provenance
figureout-0.2.4.tar.gz 20.9 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for figureout 0.2.4
File Interpreter ABI Platform
figureout-0.2.4-py3-none-any.whl Python 3 none any Details

Total release size: 38.5 kB

Release files / figureout-0.2.4.tar.gz

Download URL figureout-0.2.4.tar.gz
Size 20.9 kB
Tags Source
SHA-256 checksum
How to use checksums
e1f6881968b7cc5c1153847cfe9117d9676622eded829419f95ad85a5ee7bff3
BLAKE2b-256 checksum
How to use checksums
2bbd2d6f3620085f663762d48a99895140b7d5dc7b6c734f32694de666595598
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Release files / figureout-0.2.4-py3-none-any.whl

Download URL figureout-0.2.4-py3-none-any.whl
Size 17.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f73d799890c51a1840a97fc52693d207e988db79750037465e6193bd6b1de4cb
BLAKE2b-256 checksum
How to use checksums
f66a809aaf9a53fdd3543b13ce8fe20e9f4cb51e4333ad20ef6f47ac44ef1d06
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Security for figureout 0.2.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for figureout-0.2.4.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page