snowland-agent-core
Framework-agnostic agent engine shared by the snowland-aitool cloud web service and the local IDE MCP server.
This package contains the agent engine (AiderCore) and a lightweight
multi-agent orchestration layer (snowland_agent_core.orchestration). Framework-
specific concerns (configuration, persistence, credential lookup, audit logging)
are supplied through dependency-injected ports, so the engine also runs under a
plain CLI or inside unit tests with in-memory adapters. The orchestration layer
is built on LangGraph (langgraph.graph).
Features
- Ports & Adapters.
AiderCoretalks to abstract protocols (CredentialRepo,SessionRepo,InvocationLog). Concrete implementations are injected by the host (Django adapter or in-memory test doubles). - Single-agent engine.
AiderCore.chat(...)runs one aider turn with conversation persistence, skill injection, and tool-result plumbing. - Multi-agent orchestration.
AgentUnit/AgentRegistry/Router/Pipeline/Teamcompose agents. TheTeamcoordinator is built on a LangGraphStateGraphwith amax_stepscap. - Safety gates. Input prompt-injection checks (
check_input) and output secret-leak scans (check_output) wrap every run; the orchestration layer never bypasses the engine's gates. - Graph visualization.
Team.draw_mermaid()/export_graph_mermaid()render the LangGraphStateGraphvia LangGraph's native Mermaid export; the dependency-freeteam_to_mermaid()renderer provides the same Mermaid flowchart without importing LangGraph.
Architecture: three-repo topology
snowland-aitool-core/ # THIS repo — engine + orchestration
snowland_agent_core/
core/ # AiderCore, SessionManager, ports, config, safety, ...
orchestration/ # AgentUnit, Registry, Router, Pipeline, Team, ...
snowland-django-agent/ # Django adapter — implements the ports, reads settings
snowland_django_agent/
django_adapter/ # build_config(), get_core(), get_team(), repos
models.py / auth.py / views.py / ...
snowland-aitool/ # Host — Django web service + MCP server
mcp_server/server.py # bridges MCP tools to the Django adapter
aitool/settings.py # TEAM_DEFAULT_MAX_STEPS and other tunables
The engine is the single source of truth for execution and safety. The Django adapter and the MCP server are adapters that call into this package; they do not reimplement agent logic.
Installation
# Engine only (used by the cloud web service)
pip install .
# With the optional MCP extras (standalone MCP server)
pip install ".[mcp]"
Runtime dependencies: aider-chat, langgraph. The mcp extra adds
mcp, pydantic, anyio, uvicorn.
Package layout
snowland_agent_core/
__init__.py # __version__, VERSION
base/ # 与领域无关的抽象层:不依赖 Django / aider / 任何 LLM SDK
__init__.py # 公共 base API(BaseAgent / SkillRegistry / ContextManager / Verifier / Sandbox ...)
agent.py # BaseAgent / AgentResult / AgentCapability
ports.py # CredentialRepo / SessionRepo / InvocationLog protocols
context.py # ContextManager / MemoryStore / DictMemory
safety.py # check_input / check_output / check_command / safe_path
sandbox.py # Sandbox(路径与命令隔离)
verifier.py # Verifier(死循环护栏)
skill.py # Skill / SkillRegistry / SkillProvider
tools.py # ToolResult / ToolRegistry + 已注册的本地 hand 工具
utils.py # base 内部辅助函数(glob 匹配、纯 Python diff 应用等)
core/
__init__.py # public engine API
aider_core.py # AiderCore engine (wraps aider-chat)
session.py # SessionManager (caches per-session cores)
config.py # CoreConfig + default_config()
executor.py # bounded execution + error classification
planner.py # planning helper
toolcall.py # tool-result plumbing
capture_io.py # aider IO capture (pure, aider-only)
prompts.py # prompt templates (pure)
inmemory.py # in-memory port implementations + make_inmemory_core()
subagent.py # sub-agent execution helper
ports.py / safety.py / sandbox.py / context.py / verifier.py # 转发 shim,指向 base 对应模块(向后兼容旧导入路径)
orchestration/
__init__.py # public orchestration API
config.py # OrchestrationConfig
unit.py # AgentInput / AgentOutput / AgentUnit / AiderAgentUnit
registry.py # AgentRegistry (role name -> AgentUnit)
router.py # Router / RouteDecision / KeywordRouter / LLMRouter
pipeline.py # Pipeline (sequential AgentUnit composition)
team.py # Team coordinator (LangGraph StateGraph) + TeamResult + build_default_team()
visualization.py # team_to_mermaid / export_mermaid (no LangGraph import)
Quick start
Single agent
make_inmemory_core wires the engine with trivial in-memory ports so it can
run without a Django project (tests, CLI experiments):
from snowland_agent_core.core.inmemory import make_inmemory_core
core = make_inmemory_core("demo", workspace="/tmp/work")
result = core.chat("Refactor utils.py to use pathlib instead of os.path")
print(result["reply"])
print("edited:", result.get("edited_files"))
AiderCore.chat(message, context=None, skills=None, tool_results=None) returns
a dict with reply, edited_files, output, safety_warnings, and
gating flags (refused / terminated) when the safety gates fire.
Custom LLM endpoint (OpenAI-compatible vendors)
AiderCore routes requests through litellm. For OpenAI-compatible vendors
(zhipu / deepseek / moonshot / qwen / hunyuan) the model id is passed as-is
and custom_llm_provider is pinned to openai; the real host is selected by
api_base. Always pass api_base — an empty api_base makes litellm fall
back to https://api.openai.com/v1 and silently mis-route a zhipu call to
OpenAI. make_core_kwargs() (tests) and make_inmemory_core() forward
api_base to AiderCore.
core = make_inmemory_core(
"demo",
provider="zhipu",
model="glm-4.7-flash",
api_base="https://open.bigmodel.cn/api/paas/v4/",
api_key="<your-key>",
workspace="/tmp/work",
)
Multi-agent team
from snowland_agent_core.core.inmemory import make_inmemory_core
from snowland_agent_core.orchestration import build_default_team
# build_default_team accepts a make_core(session_id, **kwargs) -> AiderCore factory.
team = build_default_team(make_inmemory_core)
result = team.run("Implement a retry decorator with exponential backoff")
print(result.reply)
print("trace:", [step.role for step in result.trace])
The default team registers crafter, asker, and planner units plus an
implement pipeline (planner -> crafter), and routes the task with a
KeywordRouter. Set OrchestrationConfig(default_router="llm") and pass a
supervisor make_supervisor_core factory to use an LLMRouter instead.
Public API surface
Engine (snowland_agent_core.core):
AiderCore— the single-agent engine.SessionManager— caches per-sessionAiderCoreinstances.CoreConfig/default_config()— engine configuration.CredentialRepo,SessionRepo,InvocationLog— injection ports.make_inmemory_core()/make_inmemory_manager()— in-memory wiring.
Orchestration (snowland_agent_core.orchestration):
AgentInput,AgentOutput,AgentUnit,AiderAgentUnit.AgentRegistry,Router,RouteDecision,KeywordRouter,LLMRouter.Pipeline,Team,TeamResult,TeamTraceStep,build_default_team().OrchestrationConfig,team_to_mermaid(),export_mermaid().
Development & testing
# Run the test suite (standard-library unittest only; no pytest required)
python -m unittest discover -s test -t .
# Build the distribution
python -m build
License
BSD-3-Clause. See LICENSE.
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 snowland_agent_core-0.2.0.tar.gz.
File metadata
- Download URL: snowland_agent_core-0.2.0.tar.gz
- Upload date:
- Size: 82.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fca124b83d70f454cfe8808ee8e71cf437c1f2a34770842d00aa4a15887c2cd4
|
|
| MD5 |
fa28de67c4b42073b6a3d3c3cc398cff
|
|
| BLAKE2b-256 |
678c5ebea8e951bd06a61348bf20590b7b0d4fea8424b592eeee96dd4823ab2d
|
File details
Details for the file snowland_agent_core-0.2.0-py3-none-any.whl.
File metadata
- Download URL: snowland_agent_core-0.2.0-py3-none-any.whl
- Upload date:
- Size: 92.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
418920525a2fcaae1ac5bc47b4e0dd1c7de867224a6832ee8a45311e5a58e617
|
|
| MD5 |
de6c8fe744f430a37c44f13bd0cf91c2
|
|
| BLAKE2b-256 |
0a71a08ad07804d4addd72abc0e80b4e8345fab2651b368cc1fb202e97480e32
|