Xun
A mini LLM agent framework with function-based tools and sub-agent spawning.
The core codebase is compact: about 3000 lines in src/xun/*.py (mostly hand written), with comprehensive type hints.
Quick Start
Requires Python 3.12+ (PEP 695)
# 1. Install dependencies
pip install git+https://github.com/MenxLi/xun.git
# 2. Install Playwright browsers (if using the default browser tools)
playwright install
# 3. Configure environment variables (see `Configuration` section below)
vim .env
# 4. Run the agent in interactive mode
xun
Optionally, run the agent in web mode:
# - Build the web frontend (if using the web display)
make build-web
# - Start the web server at current directory
xuns .
# - Use a temporary workspace instead
xuns
xuns accepts at most one workspace directory: every session shares it, or each session gets its own temporary workspace if omitted. Session management is on by default; disable it with --no-manage-sessions.
Usage
Basic: Quickly set up an agent with plain functions as tools — no decorators, no classes needed.
from xun import setup_agent
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
agent = setup_agent(tools = [add])
agent.instruct("Add 2 and 3.").execute()
Advanced: The framework is flexible and extensible. Additional features are shown in demo.ipynb, including:
Agentconfiguration- Display extension
- Output validation
- Tool attributes
- Context injection
- Type-state transition
- Sub-agent spawning
- Lifecycle hooks
- ...
Do check out demo.ipynb for detailed examples.
CLI
Run xun in your terminal to start an interactive session.
You can also pass a prompt as an argument to begin with a specific instruction.
xun "Write a hello world python script and save it to hello.py"
Image attachments are supported in the format of [image:path_or_url]. For example:
>>> [image:cat.png image:https://example.com/dog.png] compare them.
Input /help to see the full list of commands.
Web
web_session starts the same managed web experience available through xuns:
from xun import web_session
web_session(workdir=".", base_path="/xun", manage_sessions=True)
WebDisplay provides lower-level access to the interactive web interface for custom service composition.
It can be used as a chat-based web application, or as a backend for other applications.
from xun import WebDisplay, WebDisplayService, setup_agent
display = WebDisplay(expose_files=True)
agent = setup_agent(display=display, default_tools=True)
service = WebDisplayService().mount("/", display)
service.start(blocking=True)
Open any tokenized URL printed at startup; the query token is exchanged for an HttpOnly cookie, so the browser reaches every mounted display without logging in again. API clients can use Authorization: Bearer <token>. File browsing, upload, download, and deletion require expose_files=True.
Multiple displays can share one authenticated service, each keeping its own agents, event history, and file policy:
service = WebDisplayService()
service.mount("/research", research_display)
service.mount("/coding", coding_display)
service.start(blocking=True)
display.build_routes() and display.build_app() do not add authentication — use WebDisplayService, or provide your own in a custom ASGI host.
Docker
make build-docker # builds the web frontend, then the `xun` image
xunc # sandbox: temporary workspace inside the container
xunc . # bind mount the current directory as /workspace
xunc --copy . # copy the current directory into /workspace instead
xunc runs xuns --host 0.0.0.0 in the container and publishes port 18960 (bridge mode), so the web UI is reachable from the host at the tokenized URL printed at startup. Other options: --exec CMD (e.g. --exec bash), --port LIST, --network host (avoid on macOS — not reachable from a host browser), --env PATTERNS (extra env vars to forward; XUN_*/_XUN_* are always forwarded), --image / --name.
Multiplexed server
xunx runs one temporary container per registered user, proxied through one public server:
xunx user-add alice # prints the access token
xunx user-list
xunx user-del alice # disconnects the user and removes its container
xunx serve --host 0.0.0.0 --port 18960 --port-range 20000-20100
Open http://localhost:18960/alice?token=TOKEN. Users live in $XUN_HOME/x/xunx.db; container ports are drawn randomly from --port-range and bound to host loopback only. Workspaces are temporary, and managed containers are cleaned up on shutdown (stale ones on next start). XUN_*/_XUN_* env vars except XUN_HOME are forwarded into each container.
Frontend development
The frontend development command starts both the backend and Vite with Vue DevTools:cd web
npm install
npm run dev
Open http://127.0.0.1:5173. Build a production bundle with npm run build. See web/README.md for connecting the UI to a separately managed backend.
Configuration
xun reads optional configuration from .xun/config.json (override the location with XUN_HOME); missing fields fall back to built-in defaults. Include only the fields you want to change, for example to override the model:
{
"model": {
"name": "my-model"
}
}
The config supports ${XUN_...} placeholders which are substituted from environment variables (e.g. ${XUN_OPENAI_API_KEY}), so secrets can live in a .env file instead. A placeholder with no matching environment variable causes a startup error.
| Config field | Environment variable | Description |
|---|---|---|
provider.openai_base_url |
${XUN_OPENAI_BASE_URL} |
OpenAI-compatible API endpoint. |
provider.openai_api_key |
${XUN_OPENAI_API_KEY} |
API key. |
model.name |
${XUN_OPENAI_MODEL} (empty) |
Model identifier. If the resolved value is empty, available models are auto-detected from the API. |
More configuration options are available; see the source code at src/xun/config.py.
Release files for xun-agent 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| xun_agent-1.0.0.tar.gz | 332.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| xun_agent-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 681.4 kB
Release files / xun_agent-1.0.0.tar.gz
| Download URL | xun_agent-1.0.0.tar.gz |
|---|---|
| Size | 332.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ef520d6b8ad78c43a6a06b98477f6c6951def349258158ca352b20632fee6114
|
|
BLAKE2b-256 checksum How to use checksums |
e0d5e4aa5ea9949bb9228c3df6c6a999fa9e97bb7adb1cb001d1ed5574b30ee9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / xun_agent-1.0.0-py3-none-any.whl
| Download URL | xun_agent-1.0.0-py3-none-any.whl |
|---|---|
| Size | 349.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d61407d5118ce58202ca8d7b2a4939bea4223ab5072b3c4e34c6c80f97974b1d
|
|
BLAKE2b-256 checksum How to use checksums |
e39e4ff1fa23fb49e62285b5cd16084b017c99ac4759117b15644b8a90028f7b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|