Skip to main content

LLM function calling on steroids using Abstract Syntax Trees.

Project description

🌲 treelang

PyPI - Version PyPI Downloads License: MIT

Turn your toolboxes into executable Abstract Syntax Trees (ASTs) that Large Language Models can plan in a single shot. treelang lets you express arbitrarily complex workflows, keep sensitive values out of the LLM, and reuse the resulting programs as shareable, cacheable trees.

Highlights

  • One LLM call, full plan – generate an AST for a complete solution without the expensive function-call loop.
  • Complex workflows – conditionals, higher-order functions (map, filter, reduce), and nested tool invocations all live in one tree.
  • Secure + green – the LLM never sees tool results; you evaluate nodes locally while controlling cost and compliance.
  • Model Context Protocol native – ships with an MCP client provider but can work with any tool registry through the ToolProvider abstraction.
  • Composable outputs – turn ASTs into callable tools (AST.tool) or serialize/describe them for sharing, caching, or review.

What you can build

  • Enterprise copilots that must orchestrate dozens of tools with branching logic.
  • Automations that need to fan out over datasets (e.g., score/map/filter large collections asynchronously).
  • Reusable skills: persist an AST, describe it with EvalResponse.describe(), and redeploy it as a tool on your MCP server.
  • LLM evaluation loops: ask for the tree (EvalType.TREE) to inspect reasoning before execution, or walk it immediately for answers.

Quick start

Requirements

  • Python 3.12+
  • An OpenAI API key (OPENAI_API_KEY) and optional OPENAI_MODEL override (defaults to gpt-4o-2024-11-20)
  • A source of tools: an MCP server, or your own provider implementing treelang.ai.provider.ToolProvider

Install

pip install treelang

Wire up tools (MCP)

import asyncio
from contextlib import AsyncExitStack

from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client

from treelang.ai.arborist import EvalType, OpenAIArborist
from treelang.ai.provider import MCPToolProvider


async def build_arborist(stack: AsyncExitStack) -> OpenAIArborist:
    try:
        await stack.__aenter__()
        # Connect to a streamable HTTP server
        read_stream, write_stream, _ = await stack.enter_async_context(
            streamable_http_client("http://localhost:8000/mcp")
        )

        # Create a session using the client streams
        session = await stack.enter_async_context(
            ClientSession(read_stream, write_stream)
        )

        # Initialize the connection
        await session.initialize()

        # Create the Arborist
        provider = MCPToolProvider(session)
        arborist = OpenAIArborist(provider=provider, model="gpt-4o")

        return arborist

    except Exception:
        print ("Error building the Arborist")
        await stack.aclose()
        raise

Ask a question (MCP)

async def run():
    stack = AsyncExitStack()
    arborist = await build_arborist(stack)

    response = await arborist.eval(
        query="Compare next weekend flights BOS➜SFO and summarize the cheapest option.",
        type=EvalType.WALK,  # change to EvalType.TREE to inspect the JSON AST instead
    )
    print(response.content)  # fully-evaluated tool output
    if (stack):
        await stack.aclose()

if __name__ == "__main__":
    asyncio.run(run())

Use response.jsontree with AST.parse() or AST.repr() if you want to log, cache, or transform the raw tree.

Tree-first workflow

  1. GenerateOpenAIArborist assembles an AST using your available tools.
  2. Inspect – represent the tree as JSON, describe it with EvalResponse.describe(), or pretty-print it using AST.repr().
  3. EvaluateAST.eval(tree, provider) asynchronously executes every node; the LLM never sees intermediate values.
  4. Packageawait AST.tool(tree, provider) turns a tree into a callable tool so you can add it back to your MCP server.

Architecture at a glance

  • Arborist (treelang/ai/arborist.py) – orchestrates LLM calls, maintains history via the optional Memory interface, and decides whether to return ASTs or walked results.
  • Tool providers (treelang/ai/provider.py) – abstract how tools are discovered/invoked. We ship an MCP client implementation and a template for custom providers.
  • Selectors (treelang/ai/selector.py) – plug in your own tool filtering logic; AllToolsSelector ships by default.
  • Trees (treelang/trees/tree.py) – immutable node classes plus helpers such as async traversal, repr generation, and turning trees into callable tools.

Resources & examples

  • Cookbook notebooks (cookbook/) walk through building trees, call patterns, and evaluation strategies.
  • Reproducible benchmark (evaluation/eval.py) runs versioned deterministic cases without credentials, records machine-readable quality and resource metrics, and checks them against committed regression baselines. A separate manual/scheduled live workflow records comparable model quality, latency, token, and cost evidence without exposing credentials to pull requests. See evaluation/README.md for commands and baseline policy.
  • Unit tests (tests/) cover the AST core and are a good reference for expected behavior when extending nodes.

Contributing & local development

We actively welcome contributions—see CONTRIBUTING.md for the full workflow.

Maintainers publish signed, provenance-attested releases through PyPI Trusted Publishing. See RELEASING.md for versioning, promotion, publishing, and verification instructions.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

treelang-0.10.0.tar.gz (151.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

treelang-0.10.0-py3-none-any.whl (27.4 kB view details)

Uploaded Python 3

File details

Details for the file treelang-0.10.0.tar.gz.

File metadata

  • Download URL: treelang-0.10.0.tar.gz
  • Upload date:
  • Size: 151.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for treelang-0.10.0.tar.gz
Algorithm Hash digest
SHA256 4ab0a901560feab0f43780f5831c180bbac6b43408ac9449331c003be97e8516
MD5 b93811af9eb6dacac80c2e83dcb756a0
BLAKE2b-256 f821c7d86e20718ddc0af5a71b153f85f5f6fe1600263716d3a52acfbbad9b9c

See more details on using hashes here.

Provenance

The following attestation bundles were made for treelang-0.10.0.tar.gz:

Publisher: release.yml on cs0lar/treelang

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file treelang-0.10.0-py3-none-any.whl.

File metadata

  • Download URL: treelang-0.10.0-py3-none-any.whl
  • Upload date:
  • Size: 27.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for treelang-0.10.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f6e6cf34dd81bc1985e040433170ba895d4e880f99637a10093bef5459480bda
MD5 90851b0a60ef83d62a61f4813402b1bb
BLAKE2b-256 6a29916764eba075f64c7eb187adf12764cf8055bbb5c380365703dd691377e3

See more details on using hashes here.

Provenance

The following attestation bundles were made for treelang-0.10.0-py3-none-any.whl:

Publisher: release.yml on cs0lar/treelang

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page