tulip_agent
autonomous agent with access to a tool library
Links
README
From the repo.
🌷🤖 tulip agent

A reference implementation for the tulip agent, an LLM-backed agent with access to a large number of tools via a tool library.
This approach reduces costs, enables the use of tool sets that exceed API limits or context windows, and increases flexibility with regard to the tool set used.
Key components
🔬 Function analysis
Generates OpenAI API compatible tool descriptions for Python functions via introspection
🌷 Tool library
Combines a vector store for semantic search among tools and tool execution
🤖 Agents
Specifying instructions for an agent completely overrides the base system prompts to avoid contradictions.
You can append custom instructions to the default prompts in tulip_agent.agents.prompts.
- Baseline, without tool library
BaseAgent: LLM agent without tool accessNaiveToolAgent: Includes tool descriptions for all tools availableCotToolAgent: Extends theNaiveToolAgentwith a planning step that decomposes the user input into subtasks
- Tulip variations with access to a tool library
MinimalTulipAgent: Minimal implementation; searches for tools based on the user input directlyNaiveTulipAgent: Naive implementation; searches for tools with a separate tool callCotTulipAgent: COT implementation; derives a plan for the necessary steps and searches for suitable toolsInformedCotTulipAgent: Same asCotTulipAgent, but with a brief description of the tool library's contentsPrimedCotTulipAgent: Same asCotTulipAgent, but primed with tool names based on an initial search with the user requestOneShotCotTulipAgent: Same asCotTulipAgent, but the system prompt included a brief exampleAutoTulipAgent: Fully autonomous variant; can use the search tool at any time and modify its tool library with CRUD operationsDfsTulipAgent: DFS inspired variant that leverages a DAG for keeping track of tasks and suitable tools, can create new tools
📊 Evaluation
math_eval: Math evaluationrobo_eval: Robotics evaluation using tools created for AttentiveSupport
📝 Examples
See ./examples
Setup
- Configure the model provider in
./.envfrom the project root, or export the same variables before running Tulip. Tulip does not silently fall back to OpenAI; if no provider is configured, it fails with a configuration hint.- Common Tulip settings:
# Supported values: openai, azure, or oai_compatible
TULIP_MODEL_SERVE_MODE=oai_compatible
TULIP_BASE_MODEL=llama3.2
TULIP_EMBEDDING_MODEL=mxbai-embed-large
# Optional. Used by agents that make explicit reasoning-model calls.
TULIP_REASONING_MODEL=
- OpenAI: set
TULIP_MODEL_SERVE_MODE=openai,OPENAI_API_KEY,TULIP_BASE_MODEL, andTULIP_EMBEDDING_MODEL. - Azure: set
TULIP_MODEL_SERVE_MODE=azure,AZURE_OPENAI_API_KEY,AZURE_API_VERSION,AZURE_OPENAI_ENDPOINT,TULIP_BASE_MODEL, andTULIP_EMBEDDING_MODEL. - OpenAI-compatible endpoints such as Ollama: set
TULIP_MODEL_SERVE_MODE=oai_compatible,OAI_COMPATIBLE_BASE_URL,TULIP_BASE_MODEL, andTULIP_EMBEDDING_MODEL.OAI_COMPATIBLE_API_KEYis optional and defaults toEMPTY. - Install with
uv venv --allow-existing && uv syncorpip install -e . - Check out the
examples, the robot evaluation insrc/eval/robo_eval, andexamples/local_examples.pyfor a local setup
Dev notes
- Python v3.10.11 recommended, higher versions may lead to issues with chroma during installation
- Pre-commit hooks - install with
(uv run) pre-commit install - Linting: ruff
- Formatting:
uv run ruff format - Import sorting:
uv run ruff check --fix - Tests: Run with
uv run pytest- The default test suite uses fake chat and embedding clients, so no OpenAI, Azure, or compatible endpoint API keys are required.
TODO
- Investigate
McpClientManagerstdio behavior with FastMCP when used from its background event-loop thread. The default tests mock MCP servers to stay deterministic and non-hanging.
Known issues
SQLite version incompatibility
See these troubleshooting instructions
- On Linux install pysqlite3-binary:
uv add pysqlite3-binary - Add the following to
lib/python3.10/site-packages/chromadb/__init__.pyin your venv
__import__('pysqlite3')
import sys
sys.modules['sqlite3'] = sys.modules.pop('pysqlite3')
Running the example results in a ModuleNotFoundError
Make sure to install the package itself, e.g., with uv sync or pip install -e .
Then run the example with uv run examples/calculator_example.py
Collected info
- ★ 44 stars
- ⎇ 5 forks
- Language: Python
- Source updated: 6/22/2026