Skip to main content

A lightweight agent framework

Project description

Liangent: Minimalist Lightweight Agent

Slogan: Minimalist lightweight agent, your first usable agent.

English | 中文


Liangent is a lightweight, extensible, and memory-aware agent framework designed for building LLM-based applications. It is designed to be a teaching prototype and a practical solution for simple tasks.

Unlike complex frameworks that rely on heavy planning steps, Liangent focuses on solving problems through forced tool usage constraints and dynamic prompt injection. This approach significantly reduces hallucinations and improves usability for everyday tasks.


✨ Key Features

🛡️ Local Code Sandbox

  • Safely execute Python code with AST-based validation
  • Safely execute Shell commands with whitelist/blacklist control
  • Double Security Guarantee:
    • Python: Allowed modules whitelist (math, datetime, json, random, re, collections, itertools, functools, statistics)
    • Python: Blacklisted built-in functions (open, exec, eval, compile, etc.)
    • Shell: Command whitelist (python3, ls, grep, cat, date, find)
    • Shell: Dangerous pattern blocking (;, &, `, $()
  • Process isolation with timeout protection

📉 Hallucination Reduction via Dynamic Constraints

  • Minimum Tool Usage (min_tool_use): Force the agent to use tools before answering
  • Maximum Tool Usage (max_tool_use): Prevent infinite tool calling loops
  • Dynamic Prompt Injection: If the agent attempts to answer too early, the system intercepts and forces reflection

🔧 Simple Tool Registration

  • Register tools using a simple @tool decorator
  • Dual Mode Support:
    • Native Function Calling: Works with models that support FC API (GPT-4, Claude 3, etc.)
    • Prompt-based Mode: Parses JSON from text output, compatible with any LLM
  • Automatic JSON Schema generation from Google-style docstrings

💾 Minimalist SQLite Storage

  • Zero-config persistent sessions and logs
  • Full traceability for every step
  • Support for PostgreSQL and other databases

🔍 High Observability

  • verbose=True: See tool calls, thoughts, and results
  • debug=True: See token usage, costs, and detailed step info
  • show_prompts=True: See complete prompts (System + History) sent to LLM

☁️ Serverless Ready

  • Built-in fc_handler.py for Aliyun Function Compute
  • Adaptable to AWS Lambda, Google Cloud Functions, etc.

🚀 Getting Started

1. Installation

pip install liangent

2. Initialize Project

liangent init

This generates:

  • .env: Configuration file (API Keys, limits, etc.)
  • AGENTS.md: Agent identity and behavior guidelines

Edit .env:

OPENAI_API_KEY=sk-your-key-here
OPENAI_BASE_URL=https://api.openai.com/v1
MODEL_NAME=gpt-3.5-turbo

# Tool Usage Policy
MIN_TOOL_USE=1
MAX_TOOL_USE=15
MAX_STEPS=20

# Enable native function calling for supported models
SUPPORTS_FUNCTION_CALLING=False

3. Basic Usage

Synchronous Chat

from liangent import Liangent

client = Liangent(verbose=True)
response = client.chat("What is 123 * 456?")
print(response)

Streaming Mode

from liangent import Liangent

client = Liangent()

for event in client.stream("List files in current directory"):
    evt_type = event.get("event")
    
    if evt_type == "thought":
        print(f"[Thinking] {event.get('content')}")
    elif evt_type == "item.started":
        item = event.get("data", {}).get("item", {})
        print(f"[Tool Call] {item.get('tool')}({item.get('args')})")
    elif evt_type == "item.completed":
        item = event.get("data", {}).get("item", {})
        print(f"[Tool Result] {item.get('aggregated_output')}")
    elif evt_type == "final_answer":
        print(f"[Answer] {event.get('content')}")
    elif evt_type == "usage_stats":
        content = event.get("content", {})
        print(f"[Usage] {content.get('usage')}")
        print(f"[Cost] {content.get('cost')}")

⚙️ Configuration Options

Liangent Client Parameters

Parameter Type Default Description
api_key str None OpenAI API Key (falls back to env)
base_url str None OpenAI Base URL (falls back to env)
model_name str None Model name (falls back to env)
db_url str None Database URL (:memory: if not set)
tools List[str] None List of tool names to enable (all if None)
verbose bool False Print thinking process and tool execution
debug bool False Print full debug info (implies verbose)
show_prompts bool False Print complete prompts for each step
min_tool_use int 1 Minimum tool calls before final answer
max_tool_use int 15 Maximum tool calls allowed
max_steps int 20 Maximum agent steps

Example: Forcing Tool Usage

from liangent import Liangent

# Agent must use at least 2 tools before answering
client = Liangent(
    min_tool_use=2,
    max_tool_use=10,
    max_steps=15,
    verbose=True
)

response = client.chat("What's the weather like?")

🖥️ CLI Commands

Interactive Chat

liangent chat

Start API Server

liangent start --port 8000
  • API Endpoint: http://localhost:8000/api/chat
  • API Docs: http://localhost:8000/docs

Initialize Configuration

liangent init

🔧 Custom Tools

Register custom tools using the @tool decorator. Google-style docstrings are mandatory as they generate the tool schema.

from liangent import tool

@tool
def get_weather(city: str, unit: str = "celsius") -> str:
    """
    Get current weather for a city.
    
    Args:
        city: Name of the city.
        unit: Temperature unit (celsius or fahrenheit).
    """
    # Your implementation
    return f"Weather in {city}: 22°C, Sunny"

@tool
def search_database(query: str, limit: int = 10) -> list:
    """
    Search the database for records.
    
    Args:
        query: Search query string.
        limit: Maximum number of results.
    """
    # Your implementation
    return [{"id": 1, "name": "Result 1"}]

Built-in Tools

  • python: Execute Python code in sandbox
  • shell_execute: Execute shell commands with security restrictions

📝 Customizing Agent Behavior

The AGENTS.md file defines your agent's persona and rules. It is automatically injected into the System Prompt.

# Agent Guidelines

## Identity
You are a senior Python engineer with expertise in data analysis.

## Behavior Rules
- Be concise and professional
- Always verify code logic using the python tool
- When handling file operations, list files first before reading

## Domain Knowledge
- Python best practices
- Data analysis workflows

🌐 API Server

Endpoint: POST /api/chat

Request Body

{
    "query": "Your question here",
    "session_id": "optional-session-id",
    "user_id": "default_user",
    "stream": true
}

SSE Events (when stream=true)

Event Description
meta Session metadata
status Current step status
thought Agent's thinking process
item.started Tool execution started
item.completed Tool execution completed
final_answer Final response
done Completion with usage stats
error Error occurred

☁️ Serverless Deployment

Aliyun Function Compute

  1. Set environment variables in FC console:

    • OPENAI_API_KEY
    • OPENAI_BASE_URL
    • MODEL_NAME
  2. Use fc_handler.py as entry point:

# fc_handler.py is included in the package
# Handler function: handler
  1. Deploy and invoke:
{
    "query": "Calculate 123 * 456"
}

📊 Event Types Reference

Event Data Fields Description
input_received content User query received
status content Step status (e.g., "Thinking (Step 1)...")
thought content Agent's reasoning
item.started data.item.id, tool, args Tool execution begins
item.completed data.item.id, tool, aggregated_output, exit_code Tool execution ends
prompt_info data.step, system_prompt, history Full prompt details
debug data.step, current_usage, total_cost Debug statistics
final_answer content Final response
usage_stats content.usage, content.cost Token usage and costs
error content Error message

🔒 Security Features

Python Sandbox

  • Allowed Modules: math, datetime, json, random, re, collections, itertools, functools, statistics
  • Blocked Functions: open, exec, eval, compile, input, globals, locals
  • Process Isolation: 5-second timeout, separate process execution
  • AST Validation: Pre-execution security check

Shell Sandbox

  • Allowed Commands: python3, ls, grep, cat, date, find
  • Blocked Patterns: ;, &, `, $(
  • Path Restriction: No .. traversal, project directory only
  • Timeout: 60 seconds default

📦 Project Structure

liangent/
├── __init__.py          # Exports: Liangent, tool
├── client.py            # High-level Liangent client
├── config.py            # Settings and init_config
├── cli.py               # CLI commands (init, start, chat)
├── server.py            # FastAPI server
├── types.py             # AgentState, MessageRole enums
├── core/
│   ├── agent.py         # ContextAgent implementation
│   ├── llm.py           # LLMClient (OpenAI compatible)
│   └── prompt_engine.py # Jinja2 template rendering
├── memory/
│   ├── db.py            # Database initialization
│   ├── models.py        # SQLAlchemy models
│   └── manager.py       # SessionManager
├── tools/
│   ├── registry.py      # @tool decorator and ToolRegistry
│   ├── sandbox.py       # Python sandbox (SafeExecutor)
│   ├── shell_env.py     # Shell sandbox
│   └── builtin/
│       └── shell.py     # shell_execute tool
└── prompts/
    └── system.j2        # System prompt template

License

MIT License

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

liangent-0.0.18.tar.gz (34.9 kB view details)

Uploaded Source

Built Distribution

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

liangent-0.0.18-py3-none-any.whl (36.8 kB view details)

Uploaded Python 3

File details

Details for the file liangent-0.0.18.tar.gz.

File metadata

  • Download URL: liangent-0.0.18.tar.gz
  • Upload date:
  • Size: 34.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for liangent-0.0.18.tar.gz
Algorithm Hash digest
SHA256 39c92455d17d3fcf540b9adc99da243a2a2b4fa404b15c5ae63226ba6e9950a5
MD5 6ec07792ca8d7f0bf7f5927b4bcabc8f
BLAKE2b-256 44c8467d5cea747fe3f98757e77be6648dc721054d21e73fc3574a0f74267ea5

See more details on using hashes here.

File details

Details for the file liangent-0.0.18-py3-none-any.whl.

File metadata

  • Download URL: liangent-0.0.18-py3-none-any.whl
  • Upload date:
  • Size: 36.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for liangent-0.0.18-py3-none-any.whl
Algorithm Hash digest
SHA256 9c9c0f36a239add7ead131a084c6a61e3938246f5ea1260b7298829429e601ee
MD5 836f0012d2eb94f73483bb31ef4326cd
BLAKE2b-256 7dc24bde6148d5efbcc43863a2e8106f8d084cc8764d20a7e388f635f2c0682d

See more details on using hashes here.

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