A Minimal agent runtime built on OpenAI Responses API
Project description
LiteRun 🚀
A lightweight, flexible Python framework for building custom OpenAI agents (Responses API) with tool support and structured prompt management.
Features
- Custom Agent Execution: Complete control over the agent execution loop, supporting both synchronous and streaming responses.
- Tool Support: Easy registration and execution of Python functions as tools.
- Type Safety: Strong typing for tool arguments with automatic coercion and validation.
- Prompt Templates: Structured way to build system, user, and assistant messages.
- Constants: Pre-defined constants for OpenAI roles and message types.
- Streaming Support: Built-in support for real-time streaming of agent thoughts, tool calls, and responses.
- Tool Management: Easy-to-define tools with automatic JSON schema generation (
ArgsSchema). - Event-Driven: Structured event system for granular control over the agent's execution lifecycle.
- OpenAI Compatible: Seamlessly integrates with
openai-pythonclient.
Requirements
- Python 3.10+
- OpenAI Python API library
Installation
Production
pip install literun
Development
git clone https://github.com/kaustubh-tr/literun.git
cd openai-agent
pip install -e .[dev]
Quick Start
Basic Agent
Here is a simple example of how to create an agent with a custom tool:
import os
from literun import Agent, ChatOpenAI, Tool, ArgsSchema
# 1. Define a tool function
def get_weather(location: str, unit: str = "celsius") -> str:
return f"The weather in {location} is 25 degrees {unit}."
# 2. Wrap it with Tool schema
weather_tool = Tool(
func=get_weather,
name="get_weather",
description="Get the weather for a location",
args_schema=[
ArgsSchema(
name="location",
type=str,
description="The city and state, e.g. San Francisco, CA",
),
ArgsSchema(
name="unit",
type=str,
description="The unit of temperature",
enum=["celsius", "fahrenheit"],
),
],
)
# 3. Initialize LLM and Agent
llm = ChatOpenAI(model="gpt-4o", temperature=0.7)
# 4. Initialize Agent
agent = Agent(
llm=llm,
system_prompt="You are a helpful assistant.",
tools=[weather_tool],
)
# 5. Run the Agent
result = agent.invoke(user_input="What is the weather in Tokyo?")
print(f"Final Answer: {result.final_output}")
Streaming Agent
You can also stream the agent's execution to handle events in real-time:
# ... (setup tool and agent as above)
print("Agent: ", end="", flush=True)
for result in agent.stream(user_input="What is the weather in Tokyo?"):
event = result.event
if event.type == "response.output_text.delta":
print(event.delta, end="", flush=True)
elif event.type == "response.function_call_arguments.done":
print(f"\n[Tool Call: {event.name}]")
print()
Runtime Configuration (Context Injection)
The framework allows passing a runtime context to tools using explicit context injection.
Rules:
- Define a tool function with a parameter annotated with
ToolRuntime. - The framework will automatically inject the
runtime_context(wrapped inToolRuntime) into that parameter. - Access configuration values using
ctx.{parameter}.
from typing import Dict, Any
from literun import Tool, ArgsSchema, ToolRuntime
# 1. Define tool with context
def get_weather(location: str, ctx: ToolRuntime) -> str:
"""
Returns weather info for a location.
The runtime context can include sensitive info like user_id or API keys.
"""
user_id = getattr(ctx, "user_id", "unknown_user")
api_key = getattr(ctx, "weather_api_key", None)
# Simulate fetching weather
return f"Weather for {location} fetched using API key '{api_key}' for user '{user_id}'."
# 2. Register tool
tool = Tool(
name="get_weather",
description="Get the weather for a given location",
func=get_weather,
args_schema=[
ArgsSchema(
name="location",
type=str,
description="Location for which to get the weather",
)
]
)
# 3. Setup agent
agent = Agent(
llm=ChatOpenAI(api_key="fake"),
tools=[tool]
)
# 4. Pass config at runtime
# The whole dict is passed into the 'ctx' argument
agent.invoke(
user_input="What's the weather in London?",
runtime_context={
"user_id": "user_123",
"weather_api_key": "SECRET_API_KEY_456"
}
)
Using ChatOpenAI Directly
You can also use the ChatOpenAI class directly if you don't need the agent loop (e.g., for simple, one-off LLM calls).
from literun import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o", temperature=0)
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Tell me a joke."}
]
# Synchronous call
# Returns the raw OpenAI Responses API response object
response = llm.invoke(messages=messages)
print(response.output_text)
# Or streaming call
# Returns a generator of raw OpenAI response stream events
stream = llm.stream(messages=messages)
for event in stream:
print(event)
See examples for complete runnable examples.
Project Structure
The project is organized as follows:
literun/
├── src/
│ └── literun/ # Main package source
│ ├── agent.py # Agent runtime logic
│ ├── llm.py # LLM client wrapper
│ ├── tool.py # Tool definition and execution
│ ├── events.py # Stream event types
│ └── ...
├── tests/ # Unit tests
├── examples/ # Usage examples
└── pyproject.toml # Project configuration
Testing
Run the test suite using unittest:
python -m unittest discover tests
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests:
python -m unittest discover tests - Update the example usage if needed
- Submit a pull request
License
MIT
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file literun-0.1.0.tar.gz.
File metadata
- Download URL: literun-0.1.0.tar.gz
- Upload date:
- Size: 21.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d01f72ee5e1808f7cb19dde6fd7e4ec105b195f2ceffa2dba68ad779bf08316e
|
|
| MD5 |
191977e3efdd93bcbaf3b814bc405e53
|
|
| BLAKE2b-256 |
adcb2c48b93647122739097a52c950c2a7bb86117bda259b179927a6f1fc6b0c
|
File details
Details for the file literun-0.1.0-py3-none-any.whl.
File metadata
- Download URL: literun-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3021a9e69361db058a49db5485f1ba9dd0b8a3bbc1b58a8b0477e06ac2ba05b
|
|
| MD5 |
8c32529f711136748c14ae242ab4c999
|
|
| BLAKE2b-256 |
55533a0d054d1238f61a6c32e13b1f6c44d292fba838f777bc5d7886f1095baf
|