Skip to main content

Foundry Local Python SDK (v2)

The Foundry Local Python SDK is a native Python binding for the Foundry Local C++ SDK. It lets you discover, download, load, and run inference against local AI models — chat completions (streaming and non-streaming), tool calling, embeddings, and audio transcription — directly in-process via a cffi binding to the Foundry Local native library. No separate service, no HTTP hop.

Features

  • Model Catalog – browse and search the Foundry Local model catalog
  • Model Management – download, cache, load, and unload models
  • Chat Completions – streaming and non-streaming, with first-class tool calling
  • Embeddings – text embeddings via a typed tensor API
  • Audio Transcription – speech-to-text (offline and live streaming)
  • Explicit EP Management – discover, download, and register execution providers on demand
  • Built-in Web Service – optional HTTP endpoint for multi-process scenarios
  • Native Performance – cffi (API mode) binding to the Foundry Local native library

Installation

pip install foundry-local-sdk

The wheel includes the Foundry Local native library and depends on onnxruntime and onnxruntime-genai-core on every platform. Windows wheels also include the reg-free WinML 2.x runtime.

Building from source

The Python SDK is a cffi binding compiled against sdk_v2/cpp/include/foundry_local/foundry_local_c.h. The compiled extension calls into foundry_local.{dll,so,dylib} at runtime via dlopen — the native library must already exist before the wheel is usable. Build it first:

# Windows
sdk_v2\cpp\build.bat --skip_tests

# Linux / macOS
sdk_v2/cpp/build.sh --skip_tests

The output lands where lib_loader.py will discover it automatically:

  • Windows (multi-config MSBuild): sdk_v2/cpp/build/Windows/<Config>/bin/<Config>/foundry_local.dll
  • Linux: sdk_v2/cpp/build/Linux/<Config>/bin/libfoundry_local.so
  • macOS: sdk_v2/cpp/build/macOS/<Config>/bin/libfoundry_local.dylib

To override the lookup, set FOUNDRY_LOCAL_LIB_DIR to a directory that contains foundry_local.{dll,so,dylib}.

Then build the wheel:

cd sdk_v2/python
python -m build --wheel

For editable installs during development:

pip install -e .

Installing native runtime dependencies for development / CI

foundry-local-install installs the published wheel and verifies that onnxruntime and onnxruntime_genai_core are available.

foundry-local-install

# Add --verbose to print resolved binary paths after installation.

Do not run this against a source-build / editable install. It will overwrite your pip install -e . (or any locally-built wheel install) with the published PyPI version. The source-build flow above (pip install -e . or pip install <local.whl>) already pulls the matching ORT and GenAI runtime packages via pyproject dependencies — no extra step needed.

Requirements

  • Python 3.11 or newer (single cp311-abi3 wheel works on every CPython ≥ 3.11)
  • Windows (x64), Linux (x64), or macOS (arm64)

Quick start

from foundry_local_sdk import (
    ChatSession,
    Configuration,
    FoundryLocalManager,
    MessageItem,
    Request,
    RequestOptions,
    SearchOptions,
    TextItem,
)

# 1. Initialize
config = Configuration(app_name="MyApp")
FoundryLocalManager.initialize(config)
manager = FoundryLocalManager.instance

# 2. Pick and load a model
model = manager.catalog.get_model("qwen2.5-0.5b")
model.download(lambda pct: print(f"\rDownloading: {pct:.1f}%", end="", flush=True))
print()
model.load()

# 3. Run a chat request through a typed session
with ChatSession(model) as session:
    session.set_options(RequestOptions(search=SearchOptions(temperature=0.0, max_output_tokens=128)))

    with Request().add_item(MessageItem.user("Why is the sky blue?")) as req:
        with session.process_request(req) as response:
            for item in response:
                if isinstance(item, TextItem):
                    print(item.text)

# 4. Cleanup
model.unload()

Runnable end-to-end examples live under samples/python/.

Usage

Initialization

Create a Configuration and initialize the singleton FoundryLocalManager.

from foundry_local_sdk import Configuration, FoundryLocalManager, LogLevel

config = Configuration(
    app_name="MyApp",
    model_cache_dir="/path/to/cache",                # optional
    log_level=LogLevel.INFORMATION,                   # optional (default: Warning)
)
FoundryLocalManager.initialize(config)
manager = FoundryLocalManager.instance

Discovering models

catalog = manager.catalog

# List all models in the catalog
models = catalog.list_models()

# Get a specific model by alias
model = catalog.get_model("qwen2.5-0.5b")

# Get a specific variant by ID
variant = catalog.get_model_variant("qwen2.5-0.5b-instruct-generic-cpu:4")

# Locally cached / currently loaded
cached = catalog.get_cached_models()
loaded = catalog.get_loaded_models()

Inspecting model metadata

IModel exposes metadata properties from the catalog:

model = catalog.get_model("phi-3.5-mini")

# Identity
print(model.id)             # e.g. "phi-3.5-mini-instruct-generic-gpu:3"
print(model.alias)          # e.g. "phi-3.5-mini"

# Context and token limits
print(model.context_length)  # e.g. 131072 (tokens), or None if unknown

# Modalities and capabilities
print(model.input_modalities)        # e.g. "text" or "text,image"
print(model.output_modalities)       # e.g. "text"
print(model.capabilities)            # e.g. "chat,completion"
print(model.supports_tool_calling)   # True, False, or None

# Cache / load state
print(model.is_cached)
print(model.is_loaded)

Explicit EP management

# Discover available EPs and registration status
eps = manager.discover_eps()
for ep in eps:
    print(f"{ep.name} - registered: {ep.is_registered}")

# Download and register all available EPs
result = manager.download_and_register_eps()
print(f"Success: {result.success}, Status: {result.status}")

# Download only specific EPs
result2 = manager.download_and_register_eps([eps[0].name])

Per-EP download progress

Pass a progress_callback to receive (ep_name, percent) updates as each EP downloads (percent is 0–100):

current_ep = ""

def on_progress(ep_name: str, percent: float) -> None:
    global current_ep
    if ep_name != current_ep:
        if current_ep:
            print()
        current_ep = ep_name
    print(f"\r  {ep_name}  {percent:5.1f}%", end="", flush=True)

manager.download_and_register_eps(progress_callback=on_progress)
print()

Catalog access does not block on EP downloads. Call download_and_register_eps() when you need hardware-accelerated execution providers.

Chat completions with ChatSession

from foundry_local_sdk import (
    ChatSession, MessageItem, Request, RequestOptions, SearchOptions, TextItem,
)

model = manager.catalog.get_model("qwen2.5-0.5b")
model.load()

with ChatSession(model) as session:
    session.set_options(RequestOptions(search=SearchOptions(temperature=0.0, max_output_tokens=256)))

    # Non-streaming
    with Request().add_item(MessageItem.user("What is 7 multiplied by 6?")) as req:
        with session.process_request(req) as response:
            for item in response:
                if isinstance(item, TextItem):
                    print(item.text)

    # Streaming — yields Item instances as the model produces them
    session.set_streaming(True)
    with Request().add_item(MessageItem.user("Tell me a joke")) as req:
        for item in session.process_streaming_request(req):
            if isinstance(item, TextItem):
                print(item.text, end="", flush=True)
    print()

model.unload()

ChatSession is stateful across turns. session.turn_count reports how many requests have been processed; session.undo_turns(n) rewinds history.

Multi-turn conversations

Each call to process_request extends the session's turn history. Build a new Request per turn:

with ChatSession(model) as session:
    for prompt in ["Hi!", "What's your favorite color?", "Why?"]:
        with Request().add_item(MessageItem.user(prompt)) as req:
            with session.process_request(req) as resp:
                for item in resp:
                    if isinstance(item, TextItem):
                        print(f"> {prompt}\n{item.text}\n")

Tool calling

Register tool definitions on the session, then watch for ToolCallItem in the response and reply with ToolResultItem:

import json
from foundry_local_sdk import ToolCallItem, ToolResultItem

with ChatSession(model) as session:
    session.add_tool_definition(
        name="get_weather",
        description="Get the current weather for a city.",
        json_schema=json.dumps({
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"],
        }),
    )

    with Request().add_item(MessageItem.user("What's the weather in Seattle?")) as req:
        with session.process_request(req) as resp:
            for item in resp:
                if isinstance(item, ToolCallItem):
                    args = json.loads(item.arguments)
                    result = {"temperature_c": 12, "conditions": "rain"}
                    # Send the result back on the next turn
                    with Request().add_item(
                        ToolResultItem(call_id=item.call_id, content=json.dumps(result))
                    ) as follow_up:
                        with session.process_request(follow_up) as final:
                            for it in final:
                                if isinstance(it, TextItem):
                                    print(it.text)

Embeddings with EmbeddingsSession

EmbeddingsSession accepts TextItem inputs and returns one TensorItem per input containing the embedding vector. Sessions are stateless — reuse one session for many requests.

from foundry_local_sdk import EmbeddingsSession, Request, TensorItem, TextItem

model = manager.catalog.get_model("qwen3-embedding-0.6b")
model.load()

with EmbeddingsSession(model) as session:
    # Single input
    with Request().add_item(TextItem("The quick brown fox")) as req:
        with session.process_request(req) as resp:
            tensor = next(it for it in resp if isinstance(it, TensorItem))
            print("Dimensions:", tensor.dimensions)
            print("First 5:", tensor.data[:5])

    # Batch input — one TextItem per string, one TensorItem out per input
    with Request() as req:
        for text in ["Machine learning", "Capital of France", "Rust language"]:
            req.add_item(TextItem(text))
        with session.process_request(req) as resp:
            for item in resp:
                if isinstance(item, TensorItem):
                    print(f"  dims={item.dimensions}")

model.unload()

Audio transcription

AudioSession accepts AudioItem input (PCM bytes + sample rate / channels) and produces TextItem output. See samples/python/audio-transcription/ and live-audio-transcription/ for runnable end-to-end examples covering offline files and live PCM streaming through an ItemQueue.

Web service (optional)

Start a built-in HTTP server for multi-process access:

manager.start_web_service()
print(f"Listening on: {manager.urls}")

# ... use the service ...

manager.stop_web_service()

API Reference

Manager and configuration

Class Description
Configuration SDK configuration (app name, cache dir, log level, web service settings)
FoundryLocalManager Singleton entry point — initialization, catalog access, EP management, web service
Catalog Model discovery — listing, lookup by alias / ID, cached and loaded queries
IModel Model interface — identity, metadata, lifecycle (download, load, unload), variant selection
EpInfo Discoverable execution provider info (name, is_registered)
EpDownloadResult Result of EP download / registration (success, status, registered_eps, failed_eps)
LogLevel Logging verbosity enum

Sessions

All sessions wrap a native flSession* and are context managers. Closing a session releases the native handle and aborts any in-flight streaming request.

Class Description
Session Abstract base class. Provides process_request, process_streaming_request, set_options, set_streaming, and the context-manager / _close lifecycle.
ChatSession For chat-completion and vision-language-chat models. Adds add_tool_definition, turn_count, undo_turns.
EmbeddingsSession For embeddings models. Stateless — accepts TextItem inputs, returns one TensorItem per input.
AudioSession For automatic-speech-recognition models. Accepts AudioItem input (and ItemQueue for live streaming), returns TextItem.

Common session methods:

  • process_request(request) -> Response — run synchronously, return the full response.
  • process_streaming_request(request) -> Iterator[Item] — yield items as the model produces them. Requires set_streaming(True) first. Abandoning the iterator (break, exception, gen.close()) automatically cancels the request and joins the worker thread.
  • set_options(RequestOptions) — apply session-level inference parameters (typed SearchOptions for sampling, optional tool_choice, and additional_options for passthrough).
  • set_streaming(enabled) — install or remove the native streaming callback.

Requests and responses

Class Description
Request Owns an flRequest*. Build with add_item(item) (fluent — returns self). Use as a context manager so the native handle is released. set_options(RequestOptions) applies per-request overrides.
Response Owns an flResponse*. Iterable over output items. Exposes item_count, get_item(i), finish_reason (FinishReason enum), and get_usage() (TokenUsage). Read item data inside the response's with block — items returned by get_item borrow the response's handle.
FinishReason NONE, ERROR, STOP, LENGTH, TOOL_CALLS.
TokenUsage prompt_tokens, completion_tokens, total_tokens.
RequestOptions Typed inference options passed to set_options. Wraps search: SearchOptions (sampling params: temperature, top_p, top_k, max_output_tokens, frequency_penalty, presence_penalty, seed, early_stopping, do_sample), `tool_choice: ToolChoice

Items

Item is the wire-format type for everything that flows in or out of a session — message turns, individual modality parts, tool calls, embeddings.

Class Description
Item Abstract base. item_type returns the ItemType. Item.from_native(ptr, owns) dispatches to the right subclass.
TextItem UTF-8 text. type is a TextItemType (DEFAULT, REASONING, OPENAI_JSON).
MessageItem A chat turn with a MessageRole (SYSTEM / USER / ASSISTANT / TOOL / DEVELOPER) and either a string or a list of part items (text, image, audio). Convenience factories: MessageItem.system(content), MessageItem.user(content), MessageItem.assistant(content). Borrows native pointers from supplied parts — keep the parts alive for the message's lifetime.
BytesItem Raw binary blob (e.g. a base64-decoded payload).
ImageItem Image input for vision models.
AudioItem Audio input (uri or bytes + format + sample_rate + channels).
ToolCallItem Emitted by the model when invoking a tool. Carries call_id, name, arguments (JSON string).
ToolResultItem Caller-supplied tool result. Carries call_id and content.
TensorItem Multi-dimensional tensor. Used for embedding output. Exposes dimensions, data_type (TensorDataType), and data.
ItemQueue Streaming-input queue used with AudioSession for live PCM. The queue is itself an Item and is added to a Request with transfer_ownership=False.

Enums: ItemType, TextItemType, MessageRole, TensorDataType.

CLI entry point

Function CLI name Description
foundry_local_sdk._native.installer.main foundry-local-install Install and verify native binaries (--verbose to print resolved paths)

Running tests

pip install -r requirements-dev.txt
python -m pytest test/ -v

See test/README.md for detailed test setup and structure.

License

MIT — see LICENSE.txt.

Links

Release files for foundry-local-sdk 2.0.1

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

Built distributions (wheels)

Table of built distributions (wheels) for foundry-local-sdk 2.0.1
File
foundry_local_sdk-2.0.1-cp311-abi3-win_arm64.whl CPython 3.11 abi3 Windows ARM64 Details
foundry_local_sdk-2.0.1-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details
foundry_local_sdk-2.0.1-cp311-abi3-manylinux_2_28_x86_64.whl CPython 3.11 abi3 Linux glibc 2.28+ x86-64 Details
foundry_local_sdk-2.0.1-cp311-abi3-manylinux_2_28_aarch64.whl CPython 3.11 abi3 Linux glibc 2.28+ ARM64 Details
foundry_local_sdk-2.0.1-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details

Total release size: 90.3 MB

Release files / foundry_local_sdk-2.0.1-cp311-abi3-win_arm64.whl

Download URL foundry_local_sdk-2.0.1-cp311-abi3-win_arm64.whl
Size 33.9 MB
Tags CPython 3.11 Windows ARM64 abi3
SHA-256 checksum
How to use checksums
2543f5dd8cd6681af7730b748bb0a037d35582fc1cd185926b62c948a4d4576c
BLAKE2b-256 checksum
How to use checksums
1ae0baec33fc8d09d04315f9423cd365c54843526d4a6c5b8fd6ae96865d089e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via RestSharp/106.13.0.0

Release files / foundry_local_sdk-2.0.1-cp311-abi3-win_amd64.whl

Download URL foundry_local_sdk-2.0.1-cp311-abi3-win_amd64.whl
Size 34.4 MB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
cc6e16c281e434eab5abe7c024905908e9d8e0cbe831ee3655d339298add93fd
BLAKE2b-256 checksum
How to use checksums
089dee28432fa1ce3167c129118ae4557d898bd1be95df8a9f1e40a21e9a20da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via RestSharp/106.13.0.0

Release files / foundry_local_sdk-2.0.1-cp311-abi3-manylinux_2_28_x86_64.whl

Download URL foundry_local_sdk-2.0.1-cp311-abi3-manylinux_2_28_x86_64.whl
Size 8.3 MB
Tags CPython 3.11 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
02447405f296618f293378d1549970b8a95d5dbbcddbfb5b53f4e5830ced960e
BLAKE2b-256 checksum
How to use checksums
806bafe111ce5793d962262d7dfdb7b88dc66186e44205c4af8a455473bf440c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via RestSharp/106.13.0.0

Release files / foundry_local_sdk-2.0.1-cp311-abi3-manylinux_2_28_aarch64.whl

Download URL foundry_local_sdk-2.0.1-cp311-abi3-manylinux_2_28_aarch64.whl
Size 8.1 MB
Tags CPython 3.11 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
27c34b28801f86dfe2c781d1794abcfbecaa7bb491bc1a82b0eb8262772c56b2
BLAKE2b-256 checksum
How to use checksums
6a3df488247d075087e0b98455d83ac7b1f97e506794bd67ddcd7e459bde20e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via RestSharp/106.13.0.0

Release files / foundry_local_sdk-2.0.1-cp311-abi3-macosx_11_0_arm64.whl

Download URL foundry_local_sdk-2.0.1-cp311-abi3-macosx_11_0_arm64.whl
Size 5.7 MB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
d77dd5f29080b9fc9c77f9b51b2779268370de4e6ae8ab728dde96501b2fa14f
BLAKE2b-256 checksum
How to use checksums
ab93ace19d6b51bcd6b77f9bb6c503a08d08dcb108ee5483bc382371670d4d17
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via RestSharp/106.13.0.0

Release history Release notifications | RSS feed

This release

2.0.1 This release

5 release files

1.2.4

1 release file

1.2.3

1 release file

1.2.2

1 release file

1.2.1

1 release file

1.2.0

1 release file

1.1.0

1 release file

1.0.0

1 release file

0.5.1

1 release file

0.5.0

1 release file

0.4.0

1 release file

0.3.1

1 release file

0.3.0

1 release file

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