agentlings 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/.env.example +14 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/.git +1 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/.github/workflows/ci.yml +34 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/.gitignore +12 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/CLAUDE.md +128 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/Dockerfile +11 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/README.md +367 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/agent.example.yaml +41 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/docker-compose.test.yml +27 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/logo.png +0 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/pyproject.toml +51 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/sleep.png +0 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/__init__.py +3 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/__main__.py +112 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/config.py +235 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/core/__init__.py +1 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/core/completion.py +219 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/core/llm.py +482 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/core/loop.py +134 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/core/memory_models.py +97 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/core/memory_store.py +109 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/core/models.py +231 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/core/prompt.py +146 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/core/scheduler.py +141 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/core/sleep.py +393 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/core/store.py +318 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/core/task.py +1087 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/core/telemetry.py +181 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/log.py +23 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/protocol/__init__.py +1 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/protocol/a2a.py +220 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/protocol/a2a_task_store.py +150 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/protocol/agent_card.py +83 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/protocol/mcp.py +245 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/server.py +244 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/tools/__init__.py +1 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/tools/builtins.py +307 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/tools/memory.py +104 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/src/agentlings/tools/registry.py +154 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/Dockerfile +7 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/__init__.py +0 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/agent.test.yaml +16 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/integration/__init__.py +0 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/integration/a2a_client.py +192 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/integration/conftest.py +146 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/integration/mcp_client.py +106 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/integration/test_a2a.py +111 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/integration/test_agent_card.py +45 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/integration/test_mcp.py +141 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/integration/test_task_flow.py +337 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/__init__.py +0 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/conftest.py +58 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_a2a_task_store.py +211 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_agent_card.py +85 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_completion.py +384 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_config.py +305 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_live_api.py +134 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_llm.py +220 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_logging.py +51 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_loop.py +103 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_mcp_handler.py +94 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_memory_models.py +80 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_memory_store.py +152 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_memory_tool.py +72 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_models.py +33 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_prompt.py +221 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_scheduler.py +73 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_sleep.py +198 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_store.py +508 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_task.py +1241 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_telemetry.py +46 -0
- agentlings-0.2.0/.claude/worktrees/agent-ac15d433/tests/unit/test_tools.py +299 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/.env.example +14 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/.git +1 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/.github/workflows/ci.yml +34 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/.gitignore +12 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/CLAUDE.md +128 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/Dockerfile +11 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/README.md +367 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/agent.example.yaml +41 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/docker-compose.test.yml +27 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/logo.png +0 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/pyproject.toml +51 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/sleep.png +0 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/__init__.py +3 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/__main__.py +112 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/config.py +235 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/core/__init__.py +1 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/core/completion.py +219 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/core/llm.py +482 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/core/loop.py +134 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/core/memory_models.py +97 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/core/memory_store.py +109 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/core/models.py +231 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/core/prompt.py +146 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/core/scheduler.py +141 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/core/sleep.py +393 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/core/store.py +318 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/core/task.py +1087 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/core/telemetry.py +181 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/log.py +23 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/protocol/__init__.py +1 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/protocol/a2a.py +199 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/protocol/a2a_task_store.py +139 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/protocol/agent_card.py +69 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/protocol/mcp.py +232 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/server.py +233 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/tools/__init__.py +1 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/tools/builtins.py +307 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/tools/memory.py +104 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/src/agentlings/tools/registry.py +154 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/Dockerfile +7 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/__init__.py +0 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/agent.test.yaml +16 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/integration/__init__.py +0 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/integration/a2a_client.py +158 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/integration/conftest.py +146 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/integration/mcp_client.py +106 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/integration/test_a2a.py +63 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/integration/test_agent_card.py +42 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/integration/test_mcp.py +141 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/integration/test_task_flow.py +337 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/__init__.py +0 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/conftest.py +58 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_a2a_task_store.py +210 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_agent_card.py +77 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_completion.py +384 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_config.py +305 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_live_api.py +134 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_llm.py +220 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_logging.py +51 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_loop.py +103 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_mcp_handler.py +56 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_memory_models.py +80 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_memory_store.py +152 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_memory_tool.py +72 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_models.py +33 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_prompt.py +221 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_scheduler.py +73 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_sleep.py +198 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_store.py +508 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_task.py +1241 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_telemetry.py +46 -0
- agentlings-0.2.0/.claude/worktrees/agent-af4d7e32/tests/unit/test_tools.py +299 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/.env.example +14 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/.git +1 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/.github/workflows/ci.yml +34 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/.gitignore +12 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/CLAUDE.md +128 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/Dockerfile +11 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/README.md +367 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/agent.example.yaml +41 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/docker-compose.test.yml +27 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/logo.png +0 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/pyproject.toml +51 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/sleep.png +0 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/__init__.py +3 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/__main__.py +112 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/config.py +235 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/core/__init__.py +1 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/core/completion.py +219 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/core/llm.py +482 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/core/loop.py +134 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/core/memory_models.py +97 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/core/memory_store.py +109 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/core/models.py +231 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/core/prompt.py +146 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/core/scheduler.py +141 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/core/sleep.py +393 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/core/store.py +318 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/core/task.py +1087 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/core/telemetry.py +181 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/log.py +23 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/protocol/__init__.py +1 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/protocol/a2a.py +199 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/protocol/a2a_task_store.py +139 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/protocol/agent_card.py +69 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/protocol/mcp.py +245 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/server.py +233 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/tools/__init__.py +1 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/tools/builtins.py +307 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/tools/memory.py +104 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/src/agentlings/tools/registry.py +154 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/Dockerfile +7 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/__init__.py +0 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/agent.test.yaml +16 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/integration/__init__.py +0 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/integration/a2a_client.py +158 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/integration/conftest.py +146 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/integration/mcp_client.py +106 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/integration/test_a2a.py +63 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/integration/test_agent_card.py +42 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/integration/test_mcp.py +141 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/integration/test_task_flow.py +337 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/__init__.py +0 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/conftest.py +58 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_a2a_task_store.py +210 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_agent_card.py +77 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_completion.py +384 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_config.py +305 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_live_api.py +134 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_llm.py +220 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_logging.py +51 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_loop.py +103 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_mcp_handler.py +94 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_memory_models.py +80 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_memory_store.py +152 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_memory_tool.py +72 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_models.py +33 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_prompt.py +221 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_scheduler.py +73 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_sleep.py +198 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_store.py +508 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_task.py +1241 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_telemetry.py +46 -0
- agentlings-0.2.0/.claude/worktrees/floofy-chasing-trinket/tests/unit/test_tools.py +299 -0
- agentlings-0.2.0/.env.example +14 -0
- agentlings-0.2.0/.env.test +4 -0
- agentlings-0.2.0/.github/workflows/ci.yml +34 -0
- agentlings-0.2.0/.github/workflows/publish.yml +37 -0
- agentlings-0.2.0/.gitignore +12 -0
- agentlings-0.2.0/.idea/.gitignore +15 -0
- agentlings-0.2.0/.idea/DonkeyWork-Agentlings.iml +9 -0
- agentlings-0.2.0/.idea/copilot.data.migration.ask2agent.xml +6 -0
- agentlings-0.2.0/.idea/encodings.xml +4 -0
- agentlings-0.2.0/.idea/go.imports.xml +11 -0
- agentlings-0.2.0/.idea/indexLayout.xml +8 -0
- agentlings-0.2.0/.idea/modules.xml +8 -0
- agentlings-0.2.0/.idea/projectSettingsUpdater.xml +8 -0
- agentlings-0.2.0/.idea/vcs.xml +6 -0
- agentlings-0.2.0/.idea/workspace.xml +85 -0
- agentlings-0.2.0/CLAUDE.md +129 -0
- agentlings-0.2.0/DESIGN-memory-sleep.md +505 -0
- agentlings-0.2.0/Dockerfile +11 -0
- agentlings-0.2.0/LICENSE +21 -0
- agentlings-0.2.0/PKG-INFO +406 -0
- agentlings-0.2.0/README.md +368 -0
- agentlings-0.2.0/agent.example.yaml +42 -0
- agentlings-0.2.0/docker-compose.test.yml +27 -0
- agentlings-0.2.0/logo.png +0 -0
- agentlings-0.2.0/navi_fixed.ico +0 -0
- agentlings-0.2.0/navi_full.ico +0 -0
- agentlings-0.2.0/pyproject.toml +74 -0
- agentlings-0.2.0/scripts/release.sh +79 -0
- agentlings-0.2.0/sleep.png +0 -0
- agentlings-0.2.0/src/agentlings/__init__.py +3 -0
- agentlings-0.2.0/src/agentlings/__main__.py +238 -0
- agentlings-0.2.0/src/agentlings/cli/__init__.py +1 -0
- agentlings-0.2.0/src/agentlings/cli/_migrations.py +78 -0
- agentlings-0.2.0/src/agentlings/cli/_templates.py +57 -0
- agentlings-0.2.0/src/agentlings/cli/_version.py +33 -0
- agentlings-0.2.0/src/agentlings/cli/init.py +122 -0
- agentlings-0.2.0/src/agentlings/cli/upgrade.py +89 -0
- agentlings-0.2.0/src/agentlings/config.py +260 -0
- agentlings-0.2.0/src/agentlings/core/__init__.py +1 -0
- agentlings-0.2.0/src/agentlings/core/completion.py +219 -0
- agentlings-0.2.0/src/agentlings/core/llm.py +509 -0
- agentlings-0.2.0/src/agentlings/core/loop.py +134 -0
- agentlings-0.2.0/src/agentlings/core/memory_models.py +97 -0
- agentlings-0.2.0/src/agentlings/core/memory_store.py +109 -0
- agentlings-0.2.0/src/agentlings/core/models.py +231 -0
- agentlings-0.2.0/src/agentlings/core/prompt.py +122 -0
- agentlings-0.2.0/src/agentlings/core/scheduler.py +141 -0
- agentlings-0.2.0/src/agentlings/core/sleep.py +393 -0
- agentlings-0.2.0/src/agentlings/core/store.py +318 -0
- agentlings-0.2.0/src/agentlings/core/task.py +1087 -0
- agentlings-0.2.0/src/agentlings/core/telemetry.py +181 -0
- agentlings-0.2.0/src/agentlings/log.py +23 -0
- agentlings-0.2.0/src/agentlings/migrations/__init__.py +37 -0
- agentlings-0.2.0/src/agentlings/migrations/m0001_seed.py +17 -0
- agentlings-0.2.0/src/agentlings/protocol/__init__.py +1 -0
- agentlings-0.2.0/src/agentlings/protocol/a2a.py +220 -0
- agentlings-0.2.0/src/agentlings/protocol/a2a_task_store.py +150 -0
- agentlings-0.2.0/src/agentlings/protocol/agent_card.py +83 -0
- agentlings-0.2.0/src/agentlings/protocol/mcp.py +232 -0
- agentlings-0.2.0/src/agentlings/server.py +247 -0
- agentlings-0.2.0/src/agentlings/templates/__init__.py +1 -0
- agentlings-0.2.0/src/agentlings/templates/default/.env.example +16 -0
- agentlings-0.2.0/src/agentlings/templates/default/agent.yaml +14 -0
- agentlings-0.2.0/src/agentlings/tools/__init__.py +1 -0
- agentlings-0.2.0/src/agentlings/tools/builtins.py +307 -0
- agentlings-0.2.0/src/agentlings/tools/memory.py +104 -0
- agentlings-0.2.0/src/agentlings/tools/registry.py +154 -0
- agentlings-0.2.0/tests/Dockerfile +7 -0
- agentlings-0.2.0/tests/__init__.py +0 -0
- agentlings-0.2.0/tests/agent.test.yaml +16 -0
- agentlings-0.2.0/tests/integration/__init__.py +0 -0
- agentlings-0.2.0/tests/integration/a2a_client.py +203 -0
- agentlings-0.2.0/tests/integration/conftest.py +146 -0
- agentlings-0.2.0/tests/integration/mcp_client.py +106 -0
- agentlings-0.2.0/tests/integration/test_a2a.py +111 -0
- agentlings-0.2.0/tests/integration/test_agent_card.py +45 -0
- agentlings-0.2.0/tests/integration/test_mcp.py +141 -0
- agentlings-0.2.0/tests/integration/test_ollama.py +288 -0
- agentlings-0.2.0/tests/integration/test_task_flow.py +337 -0
- agentlings-0.2.0/tests/unit/__init__.py +0 -0
- agentlings-0.2.0/tests/unit/conftest.py +58 -0
- agentlings-0.2.0/tests/unit/test_a2a_task_store.py +211 -0
- agentlings-0.2.0/tests/unit/test_agent_card.py +85 -0
- agentlings-0.2.0/tests/unit/test_cli_init.py +129 -0
- agentlings-0.2.0/tests/unit/test_cli_upgrade.py +101 -0
- agentlings-0.2.0/tests/unit/test_completion.py +384 -0
- agentlings-0.2.0/tests/unit/test_config.py +343 -0
- agentlings-0.2.0/tests/unit/test_live_api.py +134 -0
- agentlings-0.2.0/tests/unit/test_llm.py +252 -0
- agentlings-0.2.0/tests/unit/test_logging.py +51 -0
- agentlings-0.2.0/tests/unit/test_loop.py +103 -0
- agentlings-0.2.0/tests/unit/test_mcp_handler.py +56 -0
- agentlings-0.2.0/tests/unit/test_memory_models.py +80 -0
- agentlings-0.2.0/tests/unit/test_memory_store.py +152 -0
- agentlings-0.2.0/tests/unit/test_memory_tool.py +72 -0
- agentlings-0.2.0/tests/unit/test_models.py +33 -0
- agentlings-0.2.0/tests/unit/test_prompt.py +170 -0
- agentlings-0.2.0/tests/unit/test_scheduler.py +73 -0
- agentlings-0.2.0/tests/unit/test_sleep.py +198 -0
- agentlings-0.2.0/tests/unit/test_store.py +508 -0
- agentlings-0.2.0/tests/unit/test_task.py +1241 -0
- agentlings-0.2.0/tests/unit/test_telemetry.py +46 -0
- agentlings-0.2.0/tests/unit/test_tools.py +299 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
2
|
+
AGENT_API_KEY=your-agent-api-key
|
|
3
|
+
|
|
4
|
+
# Path to agent definition YAML (name, description, tools, skills, system prompt)
|
|
5
|
+
# AGENT_CONFIG=./agent.yaml
|
|
6
|
+
|
|
7
|
+
# AGENT_MODEL=claude-sonnet-4-6
|
|
8
|
+
# AGENT_MAX_TOKENS=4096
|
|
9
|
+
# AGENT_HOST=0.0.0.0
|
|
10
|
+
# AGENT_PORT=8420
|
|
11
|
+
# AGENT_DATA_DIR=./data
|
|
12
|
+
# AGENT_LOG_LEVEL=INFO
|
|
13
|
+
# AGENT_LLM_BACKEND=anthropic
|
|
14
|
+
# AGENT_EXTERNAL_URL=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
gitdir: /Users/andrewmorgan/Personal/source/DonkeyWork-Agentlings/.git/worktrees/agent-ac15d433
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
unit-tests:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.12"
|
|
18
|
+
|
|
19
|
+
- name: Install dependencies
|
|
20
|
+
run: pip install -e ".[dev]"
|
|
21
|
+
|
|
22
|
+
- name: Unit tests
|
|
23
|
+
run: pytest tests/unit/ -v
|
|
24
|
+
|
|
25
|
+
- name: Integration tests (in-process)
|
|
26
|
+
run: pytest tests/integration/ -v
|
|
27
|
+
|
|
28
|
+
docker-tests:
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v4
|
|
32
|
+
|
|
33
|
+
- name: Build and run agentling container
|
|
34
|
+
run: docker compose -f docker-compose.test.yml up --build --abort-on-container-exit --exit-code-from test-runner
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project
|
|
6
|
+
|
|
7
|
+
Agentlings — a lightweight single-process Python framework for running AI agents that expose both A2A (Agent-to-Agent Protocol v1.0) and MCP (Model Context Protocol) on a single HTTP port. Each agentling is a small, focused agent whose identity is defined by configuration (name, description, system prompt, tools), not code.
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
|
|
11
|
+
Two protocol interfaces (A2A JSON-RPC at `/a2a`, MCP Streamable HTTP at `/mcp`) feed into a shared **task engine**. Every request becomes a task with its own sub-journal; the HTTP handler awaits up to `AGENT_TASK_AWAIT_SECONDS` (default 60) and either returns the final result inline (fast path) or yields a task handle the caller polls (slow path). FIFO ordering is preserved per context — only one task can run per context at a time, so concurrent requests are rejected with `context_busy` for the LLM to retry.
|
|
12
|
+
|
|
13
|
+
Data layout:
|
|
14
|
+
|
|
15
|
+
- Parent journal: `{data_dir}/{contextId}/journal.jsonl` (conversation history)
|
|
16
|
+
- Sub-journal: `{data_dir}/{contextId}/tasks/{taskId}.jsonl` (task execution trace)
|
|
17
|
+
- Legacy `{data_dir}/{contextId}.jsonl` files are auto-migrated on first access.
|
|
18
|
+
|
|
19
|
+
Package structure under `src/agentlings/`:
|
|
20
|
+
- `config.py` — Pydantic BaseSettings, all config via env vars + `.env`
|
|
21
|
+
- `log.py` — console-first logging setup
|
|
22
|
+
- `server.py` — Starlette app wiring A2A + MCP routes, API key middleware, startup crash-recovery
|
|
23
|
+
- `core/` — task engine
|
|
24
|
+
- `task.py` — `TaskEngine`, `TaskRegistry`, `TaskWorker`, merge-back, crash recovery
|
|
25
|
+
- `loop.py` — synchronous facade over `TaskEngine` for legacy callers
|
|
26
|
+
- `llm.py` — LLM client abstraction (Anthropic + mock backends)
|
|
27
|
+
- `store.py` — JSONL append/replay with compaction cursor + `TaskJournal` (sub-journal)
|
|
28
|
+
- `models.py` — journal entry types (messages, compaction, task markers, merge wrappers)
|
|
29
|
+
- `prompt.py` — system prompt builder
|
|
30
|
+
- `completion.py` — shared LLM completion cycle with per-turn callback + cancellation
|
|
31
|
+
- `protocol/` — protocol adapters
|
|
32
|
+
- `a2a.py` — `AgentlingExecutor` bridging A2A SDK to the task engine
|
|
33
|
+
- `mcp.py` — MCP server exposing a single task-aware tool
|
|
34
|
+
- `agent_card.py` — Agent Card generation from config
|
|
35
|
+
- `tools/` — pluggable tool system
|
|
36
|
+
- `registry.py` — `ToolRegistry` with group-based registration
|
|
37
|
+
- `builtins.py` — bash and filesystem tool implementations
|
|
38
|
+
|
|
39
|
+
The Agent Card at `/.well-known/agent.json` is the single source of truth — the MCP tool schema is derived from it.
|
|
40
|
+
|
|
41
|
+
### Task engine lifecycle
|
|
42
|
+
|
|
43
|
+
1. **Ingress**: `engine.spawn(message, contextId?)` atomically admits one task per context, writes a `TaskDispatched` audit marker to the parent journal, creates a sub-journal with `TaskStarted`, and spawns a worker.
|
|
44
|
+
2. **Execution**: the worker snapshots the parent journal (replay from latest compaction cursor), runs the LLM loop via `compact_20260112`, writes each turn to the sub-journal.
|
|
45
|
+
3. **Merge-back (success)**: under the per-context lock, the engine atomically writes `MergeStarted` → user message → latest sub-journal compaction (if any) → assistant final response → `MergeCommitted` to the parent journal.
|
|
46
|
+
4. **Cancel/fail**: only a `TaskCancelled` or `TaskFailed` audit marker lands on the parent. No conversational content leaks.
|
|
47
|
+
5. **Replay**: audit markers (`task_dispatch`, `task_cancel`, `task_fail`, `merge_start`, `merge_commit`) are stripped by the store's `replay()` — they never reach the LLM.
|
|
48
|
+
6. **Crash recovery**: on startup, orphaned sub-journals get `TaskFailed { reason: "process_crash_recovery" }` and partial merge-backs are completed idempotently.
|
|
49
|
+
|
|
50
|
+
## Commands
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Install in dev mode
|
|
54
|
+
pip install -e ".[dev]"
|
|
55
|
+
|
|
56
|
+
# Run the agent
|
|
57
|
+
agentling
|
|
58
|
+
|
|
59
|
+
# Run with overrides
|
|
60
|
+
AGENT_NAME="my-agent" AGENT_PORT=9000 agentling
|
|
61
|
+
|
|
62
|
+
# Build container
|
|
63
|
+
docker build -t agentling:latest .
|
|
64
|
+
|
|
65
|
+
# Run container
|
|
66
|
+
docker run -e ANTHROPIC_API_KEY=... -e AGENT_API_KEY=... -v ./data:/data -p 8420:8420 agentling:latest
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Configuration
|
|
70
|
+
|
|
71
|
+
All via environment variables (loaded from `.env` via python-dotenv):
|
|
72
|
+
- `ANTHROPIC_API_KEY` (required)
|
|
73
|
+
- `AGENT_API_KEY` (required) — checked via `X-API-Key` header
|
|
74
|
+
- `AGENT_MODEL` (default `claude-sonnet-4-6`)
|
|
75
|
+
- `AGENT_MAX_TOKENS` (default `4096`)
|
|
76
|
+
- `AGENT_HOST` / `AGENT_PORT` (default `0.0.0.0:8420`)
|
|
77
|
+
- `AGENT_DATA_DIR` (default `./data`) — JSONL journal storage
|
|
78
|
+
- `AGENT_NAME` / `AGENT_DESCRIPTION` — identity for Agent Card + MCP tool
|
|
79
|
+
- `AGENT_SYSTEM_PROMPT_FILE` — optional path to override default system prompt
|
|
80
|
+
- `AGENT_LOG_LEVEL` (default `INFO`)
|
|
81
|
+
- `AGENT_TASK_AWAIT_SECONDS` (default `60`) — HTTP handler await timeout before yielding a task handle to the caller
|
|
82
|
+
|
|
83
|
+
## Logging
|
|
84
|
+
|
|
85
|
+
Console-only, format: `datetime - level - path - message`. All modules use `logging.getLogger(__name__)`. No third-party logging libraries.
|
|
86
|
+
|
|
87
|
+
## Design Constraints
|
|
88
|
+
|
|
89
|
+
- **Task-enabled, message-shape.** Every request becomes a task with its own sub-journal. Protocol surfaces expose task handles for long-running work, but A2A/MCP interactions are still carried as messages — no artifacts, no push notifications, no streaming.
|
|
90
|
+
- **One task per context.** FIFO is architectural, not configurable. Concurrent requests to a busy context are rejected with `context_busy`; the LLM retries.
|
|
91
|
+
- **Parent journal records only successful completions.** Cancel/fail leave only audit markers, never conversational content. Replay strips audit markers unconditionally.
|
|
92
|
+
- **contextId is the conversation handle; taskId is the execution handle.** ContextId maps to a directory; taskId is UUID4 and path-bound via `{contextId}/tasks/{taskId}.jsonl` — the filesystem enforces `(contextId, taskId)` pairing.
|
|
93
|
+
- **Confirmation is conversation** — no `input-required` state, just natural language turns.
|
|
94
|
+
- **The LLM is the agent** — the framework records and replays, it does not orchestrate.
|
|
95
|
+
- **Tools are pluggable** — register at startup, errors returned to LLM as tool results (not exceptions).
|
|
96
|
+
- **JSONL is append-only**, never modified or deleted; compaction markers are replay cursors, task compactions are ported to parent on merge-back.
|
|
97
|
+
- **Merge-back is atomic** via `MergeStarted`/`MergeCommitted` wrappers so startup recovery can repair partial writes idempotently.
|
|
98
|
+
- **MCP Session ID and contextId are independent concepts**, never cross-referenced.
|
|
99
|
+
|
|
100
|
+
## Development Methodology
|
|
101
|
+
|
|
102
|
+
**Write → Test → Continue.** Every piece of code gets tested before moving on.
|
|
103
|
+
|
|
104
|
+
- Bug workflow: write a failing test that reproduces the bug → verify it fails → fix the code → verify the test passes. No exceptions.
|
|
105
|
+
- Each task ends with tests that prove the task works.
|
|
106
|
+
- Each milestone ends with rigorous integration testing.
|
|
107
|
+
- Tests run in Docker via `docker compose` — the test harness spins up the agentling container and runs an MCP client and A2A client against it.
|
|
108
|
+
- Unit tests (pytest) for internal modules; integration tests for protocol-level behaviour.
|
|
109
|
+
- All LLM responses are mocked — tests never call the real Anthropic API or require a real key. The agentling container in integration tests runs with a mock LLM backend.
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Run unit tests
|
|
113
|
+
pytest tests/unit/
|
|
114
|
+
|
|
115
|
+
# Run integration tests (builds + runs container)
|
|
116
|
+
docker compose -f docker-compose.test.yml up --build --abort-on-container-exit
|
|
117
|
+
|
|
118
|
+
# Run all tests
|
|
119
|
+
pytest tests/unit/ && docker compose -f docker-compose.test.yml up --build --abort-on-container-exit
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Dependencies
|
|
123
|
+
|
|
124
|
+
- `anthropic` — LLM backend with `compact_20260112`
|
|
125
|
+
- `starlette` + `uvicorn` — HTTP server
|
|
126
|
+
- `pydantic` — config and models
|
|
127
|
+
- `mcp` — MCP SDK (Streamable HTTP)
|
|
128
|
+
- `python-dotenv` — env file loading
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="logo.png" alt="Agentlings" width="256">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Agentlings</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
Lightweight single-process agent framework exposing both
|
|
9
|
+
<a href="https://a2a-protocol.org">A2A</a> and
|
|
10
|
+
<a href="https://modelcontextprotocol.io">MCP</a> on a single HTTP port.
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
Each agentling is a small, focused AI agent whose identity is defined by a YAML config file — name, description, system prompt, tools, and skills. The framework handles protocol compliance, conversation journaling, and context management. The LLM is the agent; the framework records and replays.
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install -e ".[dev]"
|
|
21
|
+
|
|
22
|
+
# Create your agent definition
|
|
23
|
+
cp agent.example.yaml agent.yaml
|
|
24
|
+
|
|
25
|
+
# Run with mock LLM (no API key needed)
|
|
26
|
+
AGENT_CONFIG=./agent.yaml AGENT_LLM_BACKEND=mock AGENT_API_KEY=dev agentling
|
|
27
|
+
|
|
28
|
+
# Run with Anthropic
|
|
29
|
+
AGENT_CONFIG=./agent.yaml ANTHROPIC_API_KEY=sk-ant-... AGENT_API_KEY=your-key agentling
|
|
30
|
+
|
|
31
|
+
# See available tools
|
|
32
|
+
agentling --list-tools
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The agent serves:
|
|
36
|
+
- `GET /.well-known/agent-card.json` — A2A Agent Card (public, no auth)
|
|
37
|
+
- `POST /a2a` — A2A JSON-RPC endpoint
|
|
38
|
+
- `POST /mcp` — MCP Streamable HTTP endpoint
|
|
39
|
+
|
|
40
|
+
## Running as a daemon
|
|
41
|
+
|
|
42
|
+
### systemd (Linux)
|
|
43
|
+
|
|
44
|
+
Create `/etc/systemd/system/agentling.service`:
|
|
45
|
+
|
|
46
|
+
```ini
|
|
47
|
+
[Unit]
|
|
48
|
+
Description=Agentling
|
|
49
|
+
After=network.target
|
|
50
|
+
|
|
51
|
+
[Service]
|
|
52
|
+
Type=simple
|
|
53
|
+
User=agentling
|
|
54
|
+
WorkingDirectory=/opt/agentling
|
|
55
|
+
EnvironmentFile=/opt/agentling/.env
|
|
56
|
+
ExecStart=/opt/agentling/venv/bin/agentling
|
|
57
|
+
Restart=on-failure
|
|
58
|
+
RestartSec=5
|
|
59
|
+
|
|
60
|
+
[Install]
|
|
61
|
+
WantedBy=multi-user.target
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Set up
|
|
66
|
+
sudo useradd -r -s /bin/false agentling
|
|
67
|
+
sudo mkdir -p /opt/agentling
|
|
68
|
+
sudo python3 -m venv /opt/agentling/venv
|
|
69
|
+
sudo /opt/agentling/venv/bin/pip install agentlings
|
|
70
|
+
|
|
71
|
+
# Copy your config
|
|
72
|
+
sudo cp agent.yaml /opt/agentling/agent.yaml
|
|
73
|
+
sudo cp .env /opt/agentling/.env # ANTHROPIC_API_KEY, AGENT_API_KEY, AGENT_CONFIG=./agent.yaml
|
|
74
|
+
|
|
75
|
+
# Start
|
|
76
|
+
sudo systemctl daemon-reload
|
|
77
|
+
sudo systemctl enable --now agentling
|
|
78
|
+
sudo journalctl -u agentling -f
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### launchd (macOS)
|
|
82
|
+
|
|
83
|
+
Create `~/Library/LaunchAgents/com.donkeywork.agentling.plist`:
|
|
84
|
+
|
|
85
|
+
```xml
|
|
86
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
87
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
88
|
+
<plist version="1.0">
|
|
89
|
+
<dict>
|
|
90
|
+
<key>Label</key>
|
|
91
|
+
<string>com.donkeywork.agentling</string>
|
|
92
|
+
<key>ProgramArguments</key>
|
|
93
|
+
<array>
|
|
94
|
+
<string>/path/to/venv/bin/agentling</string>
|
|
95
|
+
</array>
|
|
96
|
+
<key>WorkingDirectory</key>
|
|
97
|
+
<string>/path/to/agentling</string>
|
|
98
|
+
<key>EnvironmentVariables</key>
|
|
99
|
+
<dict>
|
|
100
|
+
<key>AGENT_CONFIG</key>
|
|
101
|
+
<string>./agent.yaml</string>
|
|
102
|
+
<key>ANTHROPIC_API_KEY</key>
|
|
103
|
+
<string>sk-ant-...</string>
|
|
104
|
+
<key>AGENT_API_KEY</key>
|
|
105
|
+
<string>your-key</string>
|
|
106
|
+
</dict>
|
|
107
|
+
<key>KeepAlive</key>
|
|
108
|
+
<true/>
|
|
109
|
+
<key>StandardErrorPath</key>
|
|
110
|
+
<string>/tmp/agentling.err</string>
|
|
111
|
+
</dict>
|
|
112
|
+
</plist>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
launchctl load ~/Library/LaunchAgents/com.donkeywork.agentling.plist
|
|
117
|
+
tail -f /tmp/agentling.err
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Agent definition
|
|
121
|
+
|
|
122
|
+
Agent identity lives in a YAML file (`agent.yaml`):
|
|
123
|
+
|
|
124
|
+
```yaml
|
|
125
|
+
name: k3s-agentling
|
|
126
|
+
description: A k3s cluster management agent
|
|
127
|
+
|
|
128
|
+
tools:
|
|
129
|
+
- bash
|
|
130
|
+
- filesystem
|
|
131
|
+
|
|
132
|
+
skills:
|
|
133
|
+
- id: k8s-ops
|
|
134
|
+
name: Kubernetes Operations
|
|
135
|
+
description: Manage cluster resources, diagnose issues, apply manifests
|
|
136
|
+
tags: [kubernetes, k3s, devops]
|
|
137
|
+
- id: file-management
|
|
138
|
+
name: File Management
|
|
139
|
+
description: Read, write, and search configuration files
|
|
140
|
+
tags: [files, yaml]
|
|
141
|
+
|
|
142
|
+
system_prompt: |
|
|
143
|
+
You are a DevOps engineer managing a k3s Kubernetes cluster.
|
|
144
|
+
|
|
145
|
+
All configuration changes go through /mnt/lab/k3s as the source of truth.
|
|
146
|
+
Never use kubectl patch/edit/set directly — write manifests and apply them.
|
|
147
|
+
|
|
148
|
+
Before any destructive operation, describe the impact and ask for confirmation.
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Point to it with `AGENT_CONFIG=./agent.yaml`.
|
|
152
|
+
|
|
153
|
+
### Available tools
|
|
154
|
+
|
|
155
|
+
| Group | Tools | Description |
|
|
156
|
+
|-------|-------|-------------|
|
|
157
|
+
| `bash` | `bash` | Shell command execution with timeout |
|
|
158
|
+
| `filesystem` | `read_file`, `write_file`, `edit_file`, `list_directory`, `search_files` | File operations with offset/limit, find-and-replace, glob search |
|
|
159
|
+
| `memory` | `memory_edit` | Read and write the agent's persistent long-term memory |
|
|
160
|
+
|
|
161
|
+
Tools are off by default. Run `agentling --list-tools` for details.
|
|
162
|
+
|
|
163
|
+
## Docker
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
docker build -t agentling:latest .
|
|
167
|
+
docker run -e AGENT_API_KEY=your-key -e AGENT_LLM_BACKEND=mock -p 8420:8420 agentling
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Environment variables
|
|
171
|
+
|
|
172
|
+
Secrets and runtime settings stay in env vars (or `.env` file):
|
|
173
|
+
|
|
174
|
+
| Variable | Default | Description |
|
|
175
|
+
|----------|---------|-------------|
|
|
176
|
+
| `AGENT_CONFIG` | — | Path to agent YAML definition |
|
|
177
|
+
| `ANTHROPIC_API_KEY` | — | Anthropic API key (required for real LLM) |
|
|
178
|
+
| `AGENT_API_KEY` | — | API key for authenticating clients |
|
|
179
|
+
| `AGENT_MODEL` | `claude-sonnet-4-6` | Anthropic model ID |
|
|
180
|
+
| `AGENT_MAX_TOKENS` | `4096` | Max tokens per LLM response |
|
|
181
|
+
| `AGENT_HOST` | `0.0.0.0` | Bind address |
|
|
182
|
+
| `AGENT_PORT` | `8420` | Bind port |
|
|
183
|
+
| `AGENT_DATA_DIR` | `./data` | JSONL journal storage directory |
|
|
184
|
+
| `AGENT_LOG_LEVEL` | `INFO` | Log level |
|
|
185
|
+
| `AGENT_LLM_BACKEND` | `anthropic` | `anthropic` or `mock` |
|
|
186
|
+
| `AGENT_EXTERNAL_URL` | — | Public URL for Agent Card (needed in Docker/k8s) |
|
|
187
|
+
| `AGENT_OTEL_ENDPOINT` | — | OpenTelemetry collector endpoint |
|
|
188
|
+
| `AGENT_OTEL_PROTOCOL` | `http` | Collector protocol (`http` or `grpc`) |
|
|
189
|
+
| `AGENT_OTEL_INSECURE` | `true` | Disable TLS for collector connection |
|
|
190
|
+
| `AGENT_OTEL_HEADERS` | — | Comma-separated `key=value` pairs for collector auth |
|
|
191
|
+
|
|
192
|
+
## Memory
|
|
193
|
+
|
|
194
|
+
Agentlings can maintain persistent long-term memory — a curated set of key-value facts that survive across conversations. Memory transforms an agent from a tool that forgets into one that learns.
|
|
195
|
+
|
|
196
|
+
### How it works
|
|
197
|
+
|
|
198
|
+
Memory is a JSON file (`data/memory/memory.json`) containing entries like:
|
|
199
|
+
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"entries": [
|
|
203
|
+
{
|
|
204
|
+
"key": "cluster-node-count",
|
|
205
|
+
"value": "4 nodes: node1 (control), node2-4 (workers)",
|
|
206
|
+
"recorded": "2026-04-01T10:00:00Z"
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The memory block is injected into the system prompt on every LLM call, between the agent's identity and the conversation history. The agent sees its accumulated knowledge as working context, not as a separate tool call.
|
|
213
|
+
|
|
214
|
+
### The memory tool
|
|
215
|
+
|
|
216
|
+
When the `memory` tool group is enabled, the agent gets a `memory_edit` tool with three operations:
|
|
217
|
+
|
|
218
|
+
| Operation | Description |
|
|
219
|
+
|-----------|-------------|
|
|
220
|
+
| `set` | Upsert an entry by key. Updates the timestamp. |
|
|
221
|
+
| `remove` | Delete an entry by key. |
|
|
222
|
+
| `list` | Return all current entries. |
|
|
223
|
+
|
|
224
|
+
The agent decides what to remember based on its system prompt. A DevOps agent might store cluster topology and known issues. A support agent might store escalation paths and recurring problems.
|
|
225
|
+
|
|
226
|
+
### CLI
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
# Show current memory
|
|
230
|
+
agentling memory show
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Configuration
|
|
234
|
+
|
|
235
|
+
```yaml
|
|
236
|
+
memory:
|
|
237
|
+
token_budget: 2000 # max tokens for the memory block in the system prompt
|
|
238
|
+
# injection_prompt: null # override the memory/data-dir-awareness template
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Sleep cycle
|
|
242
|
+
|
|
243
|
+
<p align="center">
|
|
244
|
+
<img src="sleep.png" alt="Sleep Cycle" width="256">
|
|
245
|
+
</p>
|
|
246
|
+
|
|
247
|
+
The sleep cycle is a nightly process that journals the day's activity, consolidates new knowledge into memory, prunes stale entries, and cleans up old files. It maps to biological sleep phases.
|
|
248
|
+
|
|
249
|
+
```mermaid
|
|
250
|
+
graph LR
|
|
251
|
+
L[Light Sleep<br/>Gate check] --> D[Deep Sleep<br/>Replay & journal]
|
|
252
|
+
D --> R[REM<br/>Integrate & prune]
|
|
253
|
+
R --> H[Housekeeping<br/>Retention cleanup]
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Phase 1: Light sleep — gate check
|
|
257
|
+
|
|
258
|
+
Quick check: were there any conversations today? If not, skip everything. No LLM calls, no cost.
|
|
259
|
+
|
|
260
|
+
### Phase 2: Deep sleep — replay and file
|
|
261
|
+
|
|
262
|
+
For each conversation from today, the sleep cycle reads the JSONL journal from the last compaction marker and submits all summaries as a single **batch request** to the Anthropic Message Batches API. Batch processing runs at 50% cost and processes in parallel.
|
|
263
|
+
|
|
264
|
+
Each summary call receives the agent's system prompt (so the agent's persona shapes what it considers important), current memory, and the conversation content. The LLM returns a structured `ConversationSummary` with a narrative and memory candidates.
|
|
265
|
+
|
|
266
|
+
Results are written to `data/journals/YYYY-MM-DD.md`.
|
|
267
|
+
|
|
268
|
+
### Phase 3: REM — integrate and prune
|
|
269
|
+
|
|
270
|
+
A single LLM call receives current memory, today's journal, and all extracted memory candidates. It integrates new facts, deduplicates, reviews existing entries for staleness, and returns a `ConsolidatedMemory` — the complete updated memory store. Written atomically to `memory.json`.
|
|
271
|
+
|
|
272
|
+
### Phase 4: Housekeeping — retention cleanup
|
|
273
|
+
|
|
274
|
+
Deletes conversation JSONL files older than `conversation_retention_days` and journal files older than `journal_retention_days`.
|
|
275
|
+
|
|
276
|
+
### Configuration
|
|
277
|
+
|
|
278
|
+
```yaml
|
|
279
|
+
sleep:
|
|
280
|
+
schedule: "0 2 * * *" # cron expression (default: 2am daily)
|
|
281
|
+
journal_retention_days: 30 # keep journals for 30 days
|
|
282
|
+
conversation_retention_days: 14 # keep JSONL conversations for 14 days
|
|
283
|
+
memory_max_entries: 50 # hard cap after consolidation
|
|
284
|
+
# model: null # override model for sleep calls
|
|
285
|
+
# summary_prompt: null # override per-conversation summary prompt
|
|
286
|
+
# consolidation_prompt: null # override REM consolidation prompt
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### CLI
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
# Trigger sleep cycle manually
|
|
293
|
+
agentling sleep --date 2026-04-01
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Data directory layout
|
|
297
|
+
|
|
298
|
+
```
|
|
299
|
+
data/
|
|
300
|
+
abc123.jsonl # conversation journals (flat, as before)
|
|
301
|
+
def456.jsonl
|
|
302
|
+
memory/
|
|
303
|
+
memory.json # persistent memory store
|
|
304
|
+
journals/
|
|
305
|
+
2026-04-01.md # daily sleep journal
|
|
306
|
+
2026-04-02.md
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
The agent is told about this directory structure and can use its filesystem tools to search past journals and conversation logs for context beyond what fits in memory.
|
|
310
|
+
|
|
311
|
+
## OpenTelemetry
|
|
312
|
+
|
|
313
|
+
The sleep cycle and memory tool emit spans and metrics to an OpenTelemetry collector when telemetry is enabled.
|
|
314
|
+
|
|
315
|
+
```yaml
|
|
316
|
+
telemetry:
|
|
317
|
+
enabled: true
|
|
318
|
+
endpoint: "http://otel-collector:4318"
|
|
319
|
+
protocol: "http" # "http" or "grpc"
|
|
320
|
+
service_name: "agentling"
|
|
321
|
+
insecure: true
|
|
322
|
+
headers: # optional auth headers
|
|
323
|
+
Authorization: "Bearer your-token"
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Or via env vars: `AGENT_OTEL_ENDPOINT=http://collector:4318 AGENT_OTEL_HEADERS="Authorization=Bearer tok"`.
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
When telemetry is disabled (the default) or the OpenTelemetry packages are not installed, all instrumentation is a no-op.
|
|
330
|
+
|
|
331
|
+
## Architecture
|
|
332
|
+
|
|
333
|
+
```mermaid
|
|
334
|
+
graph TB
|
|
335
|
+
A2A[A2A Client] -->|POST /a2a| A2ASDK[a2a-sdk Server]
|
|
336
|
+
MCP[MCP Client] -->|POST /mcp| MCPSDK[mcp SDK Server]
|
|
337
|
+
A2ASDK --> Executor[AgentlingExecutor]
|
|
338
|
+
Executor --> Loop[MessageLoop]
|
|
339
|
+
MCPSDK --> Loop
|
|
340
|
+
Loop --> Store[JSONL Store]
|
|
341
|
+
Loop --> LLM[LLM Client]
|
|
342
|
+
Loop --> Tools[Tool Registry]
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Both protocols feed into a single `MessageLoop.process_message()` entrance. Conversations are persisted as append-only JSONL journals with compaction markers as replay cursors.
|
|
346
|
+
|
|
347
|
+
## Testing
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
# Unit tests (no network, no LLM)
|
|
351
|
+
pytest tests/unit/ -v
|
|
352
|
+
|
|
353
|
+
# Integration tests (starts real server with mock LLM)
|
|
354
|
+
pytest tests/integration/ -v
|
|
355
|
+
|
|
356
|
+
# All tests
|
|
357
|
+
pytest tests/ -v
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Integration tests use native SDK clients — `a2a-sdk` `ClientFactory` for A2A and `mcp` `ClientSession` for MCP — talking to a real server over HTTP. All LLM responses are mocked.
|
|
361
|
+
|
|
362
|
+
## Built with
|
|
363
|
+
|
|
364
|
+
- [a2a-sdk](https://github.com/a2aproject/a2a-python) — A2A protocol server + client
|
|
365
|
+
- [mcp](https://github.com/modelcontextprotocol/python-sdk) — MCP protocol server + client
|
|
366
|
+
- [anthropic](https://github.com/anthropics/anthropic-sdk-python) — LLM backend
|
|
367
|
+
- [starlette](https://www.starlette.io) + [uvicorn](https://www.uvicorn.org) — HTTP server
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: my-agentling
|
|
2
|
+
description: A helpful AI assistant
|
|
3
|
+
|
|
4
|
+
tools:
|
|
5
|
+
- bash
|
|
6
|
+
- filesystem
|
|
7
|
+
- memory
|
|
8
|
+
|
|
9
|
+
skills:
|
|
10
|
+
- id: general
|
|
11
|
+
name: General Assistant
|
|
12
|
+
description: Answer questions and help with tasks
|
|
13
|
+
tags: [general, assistant]
|
|
14
|
+
|
|
15
|
+
system_prompt: |
|
|
16
|
+
You are a helpful AI assistant.
|
|
17
|
+
|
|
18
|
+
Use the tools available to you to accomplish tasks. When a tool returns output,
|
|
19
|
+
incorporate it into your response.
|
|
20
|
+
|
|
21
|
+
Be concise. Use code blocks for command output.
|
|
22
|
+
|
|
23
|
+
memory:
|
|
24
|
+
token_budget: 2000
|
|
25
|
+
# injection_prompt: null # override the memory injection template
|
|
26
|
+
|
|
27
|
+
sleep:
|
|
28
|
+
schedule: "0 2 * * *"
|
|
29
|
+
journal_retention_days: 30
|
|
30
|
+
conversation_retention_days: 14
|
|
31
|
+
memory_max_entries: 50
|
|
32
|
+
# model: null # override model for sleep LLM calls
|
|
33
|
+
# summary_prompt: null # override per-conversation summary prompt
|
|
34
|
+
# consolidation_prompt: null # override REM consolidation prompt
|
|
35
|
+
|
|
36
|
+
telemetry:
|
|
37
|
+
enabled: false
|
|
38
|
+
endpoint: "http://localhost:4318"
|
|
39
|
+
protocol: "http"
|
|
40
|
+
service_name: "agentling"
|
|
41
|
+
insecure: true
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
services:
|
|
2
|
+
agentling:
|
|
3
|
+
build: .
|
|
4
|
+
environment:
|
|
5
|
+
- AGENT_API_KEY=test-key
|
|
6
|
+
- AGENT_LLM_BACKEND=mock
|
|
7
|
+
- AGENT_EXTERNAL_URL=http://agentling:8420
|
|
8
|
+
- AGENT_CONFIG=/app/tests/agent.test.yaml
|
|
9
|
+
- AGENT_LOG_LEVEL=WARNING
|
|
10
|
+
ports:
|
|
11
|
+
- "8420:8420"
|
|
12
|
+
healthcheck:
|
|
13
|
+
test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8420/.well-known/agent-card.json')"]
|
|
14
|
+
interval: 2s
|
|
15
|
+
timeout: 5s
|
|
16
|
+
retries: 15
|
|
17
|
+
|
|
18
|
+
test-runner:
|
|
19
|
+
build:
|
|
20
|
+
context: .
|
|
21
|
+
dockerfile: tests/Dockerfile
|
|
22
|
+
depends_on:
|
|
23
|
+
agentling:
|
|
24
|
+
condition: service_healthy
|
|
25
|
+
environment:
|
|
26
|
+
- AGENT_URL=http://agentling:8420
|
|
27
|
+
- AGENT_API_KEY=test-key
|
|
Binary file
|