A lightweight agent SDK built on LiteLLM, with single-agent (ReactAgent / SkillAgent / SandboxAgent), tick-driven runtime, and chat-layer multi-agent abstractions.
Project description
EasyAgent
English | 简体中文
EasyAgent is a lightweight agent SDK organised as a small set of composable layers. The goal is to let you learn agent design step by step: start with a single model call, then add memory and context, build up to a ReAct loop with tools and skills, drop into a sandbox, and finally orchestrate multiple agents through events.
Install
pip install easy-agent-sdk
From source:
git clone https://github.com/SNHuan/EasyAgent.git
cd EasyAgent
pip install -e ".[dev]"
Optional extras:
pip install easy-agent-sdk[sandbox]
pip install easy-agent-sdk[web]
pip install easy-agent-sdk[all]
Quick Start
import asyncio
from easyagent import LiteLLMModel, ReactAgent
async def main():
agent = ReactAgent(
model=LiteLLMModel("gpt-4o-mini"),
system_prompt="You are a concise assistant.",
max_iterations=5,
)
result = await agent.run("What is 2 + 2?")
print(result.final_output)
asyncio.run(main())
Create easyagent/config/config.yaml or configure LiteLLM through environment
variables:
debug: false
models:
gpt-4o-mini:
api_type: openai
base_url: https://api.openai.com/v1
api_key: sk-xxx
Layered Design
EasyAgent is organised around three concrete concepts:
Agent = reusable definition (a "role")
AgentSession = a running instance of an Agent (a "self" inside a Runtime)
Runtime = an execution environment shared by multiple sessions
The layers build up naturally:
Model
-> Memory + Context
-> Agent (Agent / ReactAgent / SkillAgent / SandboxAgent)
-> Tool / Skill / Sandbox
-> Event
-> Runtime
- Model — provider adapter and message schema.
- Memory + Context — store conversation history and decide what reaches the model each turn.
- Agent — composes a model, memory, context, and any tools/skills/sandbox
the agent needs. The four built-in classes form an inheritance chain:
Agent(single-turn) →ReactAgent(ReAct loop with tools) →SkillAgent/SandboxAgent. The loop is part of the agent's ownstep()method — there is no separateLooplayer. - Tool / Skill / Sandbox — callable functions the model can use, loadable instruction packages, and the execution environment for sandboxed tools.
- Event —
MessageEventis the structured communication primitive between agents. - Runtime — schedules multiple sessions and decides when to stop.
See docs/architecture.md for the full design guide.
Public API
The root package exposes the common SDK surface:
from easyagent import (
Agent, ReactAgent, SkillAgent, SandboxAgent, # agent classes
AgentSession, AgentRunResult, # session & result
LiteLLMModel, Message, # model layer
EventBus, MessageEvent, # events
ToolManager, SkillManager, register_tool, # tool / skill registries
)
Submodules expose advanced building blocks:
from easyagent.context import FullContext, SlidingWindowContext, SummaryContext
from easyagent.memory import InMemoryMemory
from easyagent.runtime import (
BaseRuntime, TickBasedRuntime,
ParallelRuntime, SequentialRuntime, ShuffledRuntime,
Parallel, Sequential, Shuffled, # SchedulePolicy
DeliverToRecipients, TickDriven, # StepPolicy
StopWhenIdle, StopAfterTicks, StopAfterEvents, # StopPolicy
StopWhenMessageMatches, AnyOf,
)
from easyagent.chat import (
ChatMessage, Identity, LLMTalker, Orchestrator, SharedState,
sequential, fanout, debate, chatroom, groupchat,
)
from easyagent.events import (
BaseEvent, WaitEvent,
LLMCalledEvent, LLMRespondedEvent,
ToolCalledEvent, ToolResultEvent,
)
ReactAgent is the typical entry point for tool-using agents. SkillAgent
and SandboxAgent are pre-configured ReactAgent subclasses that add skill
loading and sandbox lifecycle management respectively.
Learning Path
The examples are ordered by layer. Each one introduces one new idea:
# Single agent (00–06)
python examples/00_model_call.py # Just call the model
python examples/01_single_turn_agent.py # Compose a minimal Agent
python examples/02_memory_and_context.py # Memory + Context
python examples/03_react_with_tools.py # ReactAgent + tool calls
python examples/04_skills_lazy_loading.py # SkillAgent (SKILL.md packages)
python examples/05_sandbox_agent.py # SandboxAgent (bash, write/read file)
python examples/06_custom_tool.py # Define your own tool
# Multi-agent via the chat layer (07–13)
python examples/07_two_agents_talk.py # Talker protocol: await alice(msg)
python examples/08_sequential.py # Linear pipeline preset
python examples/09_chatroom.py # Manual turn-taking + if/else
python examples/10_groupchat.py # LLM picks next via msg.to
python examples/11_debate_and_judge.py # Third-party arbitration
python examples/12_nested.py # Orchestrator-as-Talker, nesting
python examples/13_shared_state.py # Blackboard collaboration
# Advanced: tick-based runtime (14)
python examples/14_advanced_runtime.py # Autonomous group chat with policies
Tools
from easyagent import LiteLLMModel, ReactAgent, register_tool
@register_tool
class GetWeather:
name = "get_weather"
type = "function"
description = "Get weather for a city."
parameters = {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
}
def init(self) -> None: ...
def execute(self, city: str) -> str:
return f"Sunny in {city}."
agent = ReactAgent(
model=LiteLLMModel("gpt-4o-mini"),
tools=[GetWeather],
)
Pass tool classes or instances directly via tools=[...]. The agent
automatically registers an end tool — call it to terminate the loop early.
Skills
Skills are directory packages loaded on demand. SKILL.md is the required
entry file; supporting files can live alongside it:
skills/my-skill/
├── SKILL.md
├── references/
├── templates/
├── assets/
└── scripts/
---
name: my-skill
description: One-line summary shown before loading.
allowed-tools:
- get_weather
---
# Full instructions
from easyagent import LiteLLMModel, SkillAgent
agent = SkillAgent(
model=LiteLLMModel("gpt-4o-mini"),
skills=["my-skill"],
skill_root="./skills",
)
When the model calls load_skill("my-skill"), the skill's full body is
returned and its declared tools are activated. Three additional helper tools
let the model navigate the package as needed:
load_skill # load full instructions, activate tools
list_skill_files # list packaged files
read_skill_file # read one file
run_skill_script # execute a script under scripts/
Multi-agent (chat layer)
For most multi-agent flows, reach for the chat layer rather than the
runtime layer. Wrap any BaseAgent as an LLMTalker, then compose with
one of the presets:
from easyagent import LiteLLMModel, ReactAgent
from easyagent.chat import LLMTalker, sequential
model = LiteLLMModel("gpt-4o-mini")
researcher = LLMTalker(ReactAgent(model=model, name="researcher", system_prompt="..."))
writer = LLMTalker(ReactAgent(model=model, name="writer", system_prompt="..."))
reviewer = LLMTalker(ReactAgent(model=model, name="reviewer", system_prompt="..."))
final = await sequential([researcher, writer, reviewer], "Write a product blurb.")
Available presets: sequential / fanout / chatroom / groupchat /
debate. They are all thin factories over Orchestrator, which itself
implements the Talker protocol — meaning any pipeline can be nested
inside another. See the examples/07_* through examples/13_* files
for one-concept-per-example walkthroughs.
Runtime (advanced)
The runtime layer is for tick-based scheduling and autonomous group simulation — cases where each agent runs asynchronously and the system advances in discrete ticks under custom step / stop / schedule policies.
from easyagent import MessageEvent
from easyagent.runtime import (
AnyOf, DeliverToRecipients, ShuffledRuntime,
StopAfterTicks, StopWhenIdle,
)
runtime = ShuffledRuntime(
agents={"alice": alice, "bob": bob},
step_policy=DeliverToRecipients(),
stop_policy=AnyOf([
StopWhenIdle(grace_steps=1),
StopAfterTicks(max_ticks=5),
]),
)
result = await runtime.run([
MessageEvent(sender="user", to="*", content="Discuss lunch options.")
])
A runtime can also be wrapped as a Talker (RuntimeTalker) and dropped
into the chat layer — the two layers compose either direction.
Module Layout
easyagent/
├── agent/ # Agent, ReactAgent, SkillAgent, SandboxAgent, AgentSession
├── chat/ # ChatMessage, Talker, Orchestrator, presets, MultiAgentFormatter
├── context/ # FullContext, SlidingWindowContext, SummaryContext
├── events/ # MessageEvent, WaitEvent, EventBus, telemetry events
├── memory/ # InMemoryMemory
├── model/ # LiteLLMModel + Message schema
├── prompt/ # System-prompt builders
├── runtime/ # TickBasedRuntime, policies (advanced/tick-based simulation)
├── sandbox/ # Local / Docker sandboxes
├── skill/ # SKILL.md loading
├── tool/ # Tool registry + built-ins (bash, file, web, end)
├── config/ # Config loading
└── debug/ # Logging
License
MIT License © 2025 Yiran Peng
Project details
Release history Release notifications | RSS feed
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 easy_agent_sdk-0.3.0.tar.gz.
File metadata
- Download URL: easy_agent_sdk-0.3.0.tar.gz
- Upload date:
- Size: 109.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea177a9f4717ad520b1a0e117a698948d45f0250f91a0fc6b88b0b1a3f6ab536
|
|
| MD5 |
a0dd8cd5f4603f2b202fba2cbe22e19e
|
|
| BLAKE2b-256 |
4aaaf2c9f07ffcfbfbcdd56d595127e5add4967aed96fd9e6eb65b4e788c429c
|
Provenance
The following attestation bundles were made for easy_agent_sdk-0.3.0.tar.gz:
Publisher:
publish.yml on SNHuan/EasyAgent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
easy_agent_sdk-0.3.0.tar.gz -
Subject digest:
ea177a9f4717ad520b1a0e117a698948d45f0250f91a0fc6b88b0b1a3f6ab536 - Sigstore transparency entry: 1396166653
- Sigstore integration time:
-
Permalink:
SNHuan/EasyAgent@4026e655bc51acef30202e9d2c0bb0bb27e74a5b -
Branch / Tag:
refs/tags/v0.3 - Owner: https://github.com/SNHuan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4026e655bc51acef30202e9d2c0bb0bb27e74a5b -
Trigger Event:
release
-
Statement type:
File details
Details for the file easy_agent_sdk-0.3.0-py3-none-any.whl.
File metadata
- Download URL: easy_agent_sdk-0.3.0-py3-none-any.whl
- Upload date:
- Size: 102.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f80e0b7047d0fed30c986bb2b9a51965f7474f66b08c98db090857e2102feff
|
|
| MD5 |
c54d77a538b49aac3c66358e04e05b74
|
|
| BLAKE2b-256 |
63ec13ddd83db018540a5aece1af561b583287e92479aecbe60723ebff5a95d8
|
Provenance
The following attestation bundles were made for easy_agent_sdk-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on SNHuan/EasyAgent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
easy_agent_sdk-0.3.0-py3-none-any.whl -
Subject digest:
6f80e0b7047d0fed30c986bb2b9a51965f7474f66b08c98db090857e2102feff - Sigstore transparency entry: 1396166671
- Sigstore integration time:
-
Permalink:
SNHuan/EasyAgent@4026e655bc51acef30202e9d2c0bb0bb27e74a5b -
Branch / Tag:
refs/tags/v0.3 - Owner: https://github.com/SNHuan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4026e655bc51acef30202e9d2c0bb0bb27e74a5b -
Trigger Event:
release
-
Statement type: