loopengt 0.1.0__py3-none-any.whl

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.
Files changed (87) hide show
  1. loopengt/__init__.py +31 -0
  2. loopengt/adapters/__init__.py +1 -0
  3. loopengt/adapters/antigravity/__init__.py +1 -0
  4. loopengt/adapters/antigravity/adapter.py +55 -0
  5. loopengt/adapters/antigravity/commands.py +21 -0
  6. loopengt/adapters/base.py +51 -0
  7. loopengt/adapters/claude_code/__init__.py +1 -0
  8. loopengt/adapters/claude_code/adapter.py +55 -0
  9. loopengt/adapters/claude_code/commands.py +16 -0
  10. loopengt/adapters/codex/__init__.py +1 -0
  11. loopengt/adapters/codex/adapter.py +52 -0
  12. loopengt/adapters/codex/commands.py +16 -0
  13. loopengt/adapters/cursor/__init__.py +1 -0
  14. loopengt/adapters/cursor/adapter.py +56 -0
  15. loopengt/adapters/cursor/commands.py +29 -0
  16. loopengt/adapters/generic/__init__.py +1 -0
  17. loopengt/adapters/generic/terminal.py +82 -0
  18. loopengt/cli/__init__.py +1 -0
  19. loopengt/cli/commands/__init__.py +1 -0
  20. loopengt/cli/commands/design.py +171 -0
  21. loopengt/cli/commands/doctor.py +110 -0
  22. loopengt/cli/commands/eval.py +105 -0
  23. loopengt/cli/commands/init.py +131 -0
  24. loopengt/cli/commands/mcp_serve.py +57 -0
  25. loopengt/cli/commands/run.py +99 -0
  26. loopengt/cli/commands/template.py +145 -0
  27. loopengt/cli/commands/trace.py +114 -0
  28. loopengt/cli/formatters.py +125 -0
  29. loopengt/cli/main.py +66 -0
  30. loopengt/core/__init__.py +1 -0
  31. loopengt/core/evals/__init__.py +1 -0
  32. loopengt/core/evals/judges.py +216 -0
  33. loopengt/core/evals/metrics.py +119 -0
  34. loopengt/core/evals/regression.py +157 -0
  35. loopengt/core/memory/__init__.py +1 -0
  36. loopengt/core/memory/retrieval.py +124 -0
  37. loopengt/core/memory/store.py +184 -0
  38. loopengt/core/memory/summarizer.py +97 -0
  39. loopengt/core/models/__init__.py +43 -0
  40. loopengt/core/models/agent.py +126 -0
  41. loopengt/core/models/loop_spec.py +251 -0
  42. loopengt/core/models/policy.py +131 -0
  43. loopengt/core/models/state.py +271 -0
  44. loopengt/core/models/tool.py +105 -0
  45. loopengt/core/runtime/__init__.py +1 -0
  46. loopengt/core/runtime/checkpoint.py +152 -0
  47. loopengt/core/runtime/executor.py +463 -0
  48. loopengt/core/runtime/handoff.py +139 -0
  49. loopengt/core/runtime/scheduler.py +168 -0
  50. loopengt/core/tracing/__init__.py +1 -0
  51. loopengt/core/tracing/events.py +95 -0
  52. loopengt/core/tracing/exporters.py +158 -0
  53. loopengt/core/tracing/store.py +202 -0
  54. loopengt/mcp/__init__.py +1 -0
  55. loopengt/mcp/client/__init__.py +1 -0
  56. loopengt/mcp/client/manager.py +118 -0
  57. loopengt/mcp/client/tools.py +107 -0
  58. loopengt/mcp/server/__init__.py +1 -0
  59. loopengt/mcp/server/prompts.py +82 -0
  60. loopengt/mcp/server/resources.py +75 -0
  61. loopengt/mcp/server/server.py +50 -0
  62. loopengt/mcp/server/tools.py +214 -0
  63. loopengt/mcp/shared/__init__.py +1 -0
  64. loopengt/mcp/shared/schemas.py +91 -0
  65. loopengt/plugins/__init__.py +1 -0
  66. loopengt/plugins/base.py +90 -0
  67. loopengt/plugins/loader.py +130 -0
  68. loopengt/plugins/manifest.py +70 -0
  69. loopengt/plugins/registry.py +146 -0
  70. loopengt/prompts/LOOPENGT.md +60 -0
  71. loopengt/prompts/__init__.py +1 -0
  72. loopengt/storage/__init__.py +1 -0
  73. loopengt/storage/jsonl.py +84 -0
  74. loopengt/storage/sqlite.py +102 -0
  75. loopengt/templates/__init__.py +1 -0
  76. loopengt/templates/builtins/handoff_loop/LOOPENGS.md +10 -0
  77. loopengt/templates/builtins/planner_executor/LOOPENGS.md +29 -0
  78. loopengt/templates/builtins/research_architect/LOOPENGS.md +17 -0
  79. loopengt/templates/builtins/reviewer_retry/LOOPENGS.md +29 -0
  80. loopengt/templates/builtins/supervisor_workers/LOOPENGS.md +29 -0
  81. loopengt/templates/loader.py +38 -0
  82. loopengt/templates/registry.py +85 -0
  83. loopengt-0.1.0.dist-info/METADATA +275 -0
  84. loopengt-0.1.0.dist-info/RECORD +87 -0
  85. loopengt-0.1.0.dist-info/WHEEL +4 -0
  86. loopengt-0.1.0.dist-info/entry_points.txt +8 -0
  87. loopengt-0.1.0.dist-info/licenses/LICENSE +674 -0
@@ -0,0 +1,102 @@
1
+ """SQLite storage backend for traces and checkpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ import structlog
10
+
11
+ logger = structlog.get_logger(__name__)
12
+
13
+
14
+ class SQLiteStorage:
15
+ """General-purpose async SQLite storage.
16
+
17
+ Wraps ``aiosqlite`` and provides convenience methods for common
18
+ operations used by the trace and checkpoint subsystems.
19
+
20
+ Usage::
21
+
22
+ storage = SQLiteStorage(Path(".loopengt/data.db"))
23
+ async with storage:
24
+ await storage.execute("INSERT INTO ...", ...)
25
+ """
26
+
27
+ def __init__(self, db_path: Path) -> None:
28
+ self._db_path = db_path
29
+ self._db: Any = None
30
+ self._log = logger.bind(component="sqlite", path=str(db_path))
31
+
32
+ async def __aenter__(self) -> "SQLiteStorage":
33
+ await self.open()
34
+ return self
35
+
36
+ async def __aexit__(self, *args: Any) -> None:
37
+ await self.close()
38
+
39
+ async def open(self) -> None:
40
+ """Open the database connection."""
41
+ import aiosqlite
42
+
43
+ self._db_path.parent.mkdir(parents=True, exist_ok=True)
44
+ self._db = await aiosqlite.connect(str(self._db_path))
45
+ await self._db.execute("PRAGMA journal_mode=WAL")
46
+ self._log.debug("sqlite.opened")
47
+
48
+ async def close(self) -> None:
49
+ """Close the database connection."""
50
+ if self._db:
51
+ await self._db.close()
52
+ self._db = None
53
+ self._log.debug("sqlite.closed")
54
+
55
+ async def execute(self, sql: str, params: tuple[Any, ...] = ()) -> Any:
56
+ """Execute a SQL statement."""
57
+ if self._db is None:
58
+ raise RuntimeError("Database not open. Call open() first.")
59
+ cursor = await self._db.execute(sql, params)
60
+ await self._db.commit()
61
+ return cursor
62
+
63
+ async def executemany(
64
+ self, sql: str, params_seq: list[tuple[Any, ...]]
65
+ ) -> None:
66
+ """Execute a SQL statement with multiple parameter sets."""
67
+ if self._db is None:
68
+ raise RuntimeError("Database not open. Call open() first.")
69
+ await self._db.executemany(sql, params_seq)
70
+ await self._db.commit()
71
+
72
+ async def fetchall(
73
+ self, sql: str, params: tuple[Any, ...] = ()
74
+ ) -> list[dict[str, Any]]:
75
+ """Execute a query and return all rows as dicts."""
76
+ if self._db is None:
77
+ raise RuntimeError("Database not open. Call open() first.")
78
+ cursor = await self._db.execute(sql, params)
79
+ rows = await cursor.fetchall()
80
+ columns = [desc[0] for desc in cursor.description]
81
+ return [dict(zip(columns, row)) for row in rows]
82
+
83
+ async def fetchone(
84
+ self, sql: str, params: tuple[Any, ...] = ()
85
+ ) -> dict[str, Any] | None:
86
+ """Execute a query and return the first row as a dict."""
87
+ if self._db is None:
88
+ raise RuntimeError("Database not open. Call open() first.")
89
+ cursor = await self._db.execute(sql, params)
90
+ row = await cursor.fetchone()
91
+ if row is None:
92
+ return None
93
+ columns = [desc[0] for desc in cursor.description]
94
+ return dict(zip(columns, row))
95
+
96
+ async def table_exists(self, table_name: str) -> bool:
97
+ """Check whether a table exists."""
98
+ result = await self.fetchone(
99
+ "SELECT name FROM sqlite_master WHERE type='table' AND name=?",
100
+ (table_name,),
101
+ )
102
+ return result is not None
@@ -0,0 +1 @@
1
+ """Template management package."""
@@ -0,0 +1,10 @@
1
+ # Handoff Loop Pattern
2
+
3
+ ## Purpose
4
+ A sequential chain where each agent processes and hands off enriched
5
+ context to the next agent in the pipeline.
6
+
7
+ ## When to Use
8
+ - Multi-stage document processing pipelines
9
+ - Data transformation chains
10
+ - Any workflow where each stage enriches the previous output
@@ -0,0 +1,29 @@
1
+ # Planner-Executor Pattern
2
+
3
+ ## Purpose
4
+ A sequential two-agent pattern where a **Planner** analyses the goal and
5
+ produces a structured action plan, then an **Executor** carries out each
6
+ step of that plan.
7
+
8
+ ## When to Use
9
+ - Tasks with clear decomposition into planning and execution phases
10
+ - Code generation, refactoring, and migration tasks
11
+ - Document drafting and editing workflows
12
+
13
+ ## Agents
14
+ | Agent | Role |
15
+ |----------|-----------------------------------------|
16
+ | planner | Analyses the goal, produces action plan |
17
+ | executor | Executes each step of the plan |
18
+
19
+ ## Steps
20
+ 1. **plan** — Planner analyses the goal and outputs a structured plan
21
+ 2. **execute** — Executor follows the plan step-by-step
22
+
23
+ ## Verification
24
+ - Plan must contain at least one actionable step
25
+ - Executor output must address all plan items
26
+
27
+ ## Risks
28
+ - Planner may produce overly complex plans → mitigate with max_steps
29
+ - Executor may deviate from plan → add plan-adherence verification gate
@@ -0,0 +1,17 @@
1
+ # Research-Architect Pattern
2
+
3
+ ## Purpose
4
+ A three-phase workflow: **Research** gathers context, **Synthesiser**
5
+ distils findings, and **Architect** produces a design based on synthesis.
6
+
7
+ ## When to Use
8
+ - System design and architecture tasks
9
+ - Technical specification writing
10
+ - Literature review → analysis → recommendation workflows
11
+
12
+ ## Agents
13
+ | Agent | Role |
14
+ |-------------|--------------------------------------------|
15
+ | researcher | Deep research on the topic |
16
+ | synthesiser | Distils research into key findings |
17
+ | architect | Designs solution based on synthesis |
@@ -0,0 +1,29 @@
1
+ # Reviewer-Retry Pattern
2
+
3
+ ## Purpose
4
+ An iterative loop where a **Worker** produces output, a **Reviewer**
5
+ evaluates it, and the worker retries with feedback until the review passes.
6
+
7
+ ## When to Use
8
+ - Code review workflows
9
+ - Content quality assurance
10
+ - Any task requiring iterative refinement based on feedback
11
+
12
+ ## Agents
13
+ | Agent | Role |
14
+ |----------|-------------------------------------------|
15
+ | worker | Produces initial output and revisions |
16
+ | reviewer | Evaluates output and provides feedback |
17
+
18
+ ## Steps
19
+ 1. **produce** — Worker creates initial output
20
+ 2. **review** — Reviewer evaluates and provides feedback
21
+ 3. **revise** — Worker revises based on feedback (loops back to review)
22
+
23
+ ## Verification
24
+ - Reviewer must provide explicit pass/fail verdict
25
+ - Max 3 revision cycles to prevent infinite loops
26
+
27
+ ## Risks
28
+ - Infinite revision loops → enforced by max_turns policy
29
+ - Reviewer may be too strict → add quality_threshold stop condition
@@ -0,0 +1,29 @@
1
+ # Supervisor-Workers Pattern
2
+
3
+ ## Purpose
4
+ A **Supervisor** agent analyses the goal and delegates sub-tasks to
5
+ specialised **Worker** agents, then aggregates results.
6
+
7
+ ## When to Use
8
+ - Complex tasks requiring multiple specialisations
9
+ - Parallel workstreams that need coordination
10
+ - Tasks where different expertise is needed for different parts
11
+
12
+ ## Agents
13
+ | Agent | Role |
14
+ |-------------|-----------------------------------------------|
15
+ | supervisor | Decomposes goal, delegates, aggregates results|
16
+ | researcher | Gathers information and context |
17
+ | implementer | Writes code or produces artifacts |
18
+ | tester | Validates and tests outputs |
19
+
20
+ ## Steps
21
+ 1. **decompose** — Supervisor analyses goal and creates sub-tasks
22
+ 2. **research** — Researcher gathers relevant context
23
+ 3. **implement** — Implementer produces the work product
24
+ 4. **test** — Tester validates the output
25
+ 5. **aggregate** — Supervisor combines and reviews all results
26
+
27
+ ## Verification
28
+ - Each worker output must pass supervisor validation
29
+ - Final aggregate must satisfy the original goal
@@ -0,0 +1,38 @@
1
+ """Template loader — YAML to LoopSpec conversion."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ import yaml
9
+
10
+ from loopengt.core.models.loop_spec import LoopSpec
11
+
12
+
13
+ class TemplateLoader:
14
+ """Loads loop templates from YAML files and converts to LoopSpec.
15
+
16
+ Usage::
17
+
18
+ loader = TemplateLoader()
19
+ spec = loader.load(Path("loop.yaml"))
20
+ """
21
+
22
+ def load(self, path: Path) -> LoopSpec:
23
+ """Load a loop.yaml and validate it as a LoopSpec."""
24
+ raw = yaml.safe_load(path.read_text(encoding="utf-8"))
25
+ return LoopSpec.model_validate(raw)
26
+
27
+ def load_dict(self, data: dict[str, Any]) -> LoopSpec:
28
+ """Validate a dict as a LoopSpec."""
29
+ return LoopSpec.model_validate(data)
30
+
31
+ def dump(self, spec: LoopSpec, path: Path) -> None:
32
+ """Serialize a LoopSpec to YAML and write to a file."""
33
+ data = spec.model_dump(mode="json", exclude_none=True)
34
+ path.parent.mkdir(parents=True, exist_ok=True)
35
+ path.write_text(
36
+ yaml.dump(data, default_flow_style=False, sort_keys=False),
37
+ encoding="utf-8",
38
+ )
@@ -0,0 +1,85 @@
1
+ """Template discovery from built-ins and plugins."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ import structlog
9
+
10
+ logger = structlog.get_logger(__name__)
11
+
12
+
13
+ class BuiltinTemplateProvider:
14
+ """Provides built-in loop templates bundled with loopengt."""
15
+
16
+ TEMPLATE_NAMES = [
17
+ "planner_executor",
18
+ "reviewer_retry",
19
+ "supervisor_workers",
20
+ "research_architect",
21
+ "handoff_loop",
22
+ ]
23
+
24
+ def list_templates(self) -> list[dict[str, str]]:
25
+ """List available built-in templates."""
26
+ return [{"name": name, "source": "builtin"} for name in self.TEMPLATE_NAMES]
27
+
28
+ def get_template_path(self, name: str) -> Path | None:
29
+ """Get the path to a built-in template directory."""
30
+ try:
31
+ from importlib.resources import files
32
+
33
+ pkg = files("loopengt.templates.builtins").joinpath(name) # type: ignore[union-attr]
34
+ return Path(str(pkg))
35
+ except Exception:
36
+ return None
37
+
38
+
39
+ class TemplateRegistry:
40
+ """Registry that discovers templates from multiple sources.
41
+
42
+ Sources:
43
+ 1. Built-in templates (loopengt.templates.builtins)
44
+ 2. Project-local templates (.loopengt/templates/)
45
+ 3. Plugin-provided templates (loopengt.templates entry point)
46
+ """
47
+
48
+ def __init__(self, local_dir: Path | None = None) -> None:
49
+ self._local_dir = local_dir or Path(".loopengt/templates")
50
+ self._builtin = BuiltinTemplateProvider()
51
+ self._log = logger.bind(component="template_registry")
52
+
53
+ def list_all(self) -> list[dict[str, str]]:
54
+ """List all available templates from all sources."""
55
+ templates = self._builtin.list_templates()
56
+
57
+ # Local templates
58
+ if self._local_dir.exists():
59
+ for entry in sorted(self._local_dir.iterdir()):
60
+ if entry.is_dir() and (entry / "loop.yaml").exists():
61
+ if entry.name not in BuiltinTemplateProvider.TEMPLATE_NAMES:
62
+ templates.append({
63
+ "name": entry.name,
64
+ "source": "local",
65
+ })
66
+
67
+ return templates
68
+
69
+ def get_template(self, name: str) -> dict[str, Any] | None:
70
+ """Load a template's loop.yaml as a dict."""
71
+ import yaml
72
+
73
+ # Check local first
74
+ local_path = self._local_dir / name / "loop.yaml"
75
+ if local_path.exists():
76
+ return yaml.safe_load(local_path.read_text(encoding="utf-8")) # type: ignore[no-any-return]
77
+
78
+ # Check built-ins
79
+ builtin_path = self._builtin.get_template_path(name)
80
+ if builtin_path:
81
+ yaml_path = builtin_path / "loop.yaml"
82
+ if yaml_path.exists():
83
+ return yaml.safe_load(yaml_path.read_text(encoding="utf-8")) # type: ignore[no-any-return]
84
+
85
+ return None
@@ -0,0 +1,275 @@
1
+ Metadata-Version: 2.4
2
+ Name: loopengt
3
+ Version: 0.1.0
4
+ Summary: Loop Engineering Agent — design, orchestrate, and evaluate agent loops
5
+ Project-URL: Homepage, https://github.com/Sriramdayal/LOOPENGT
6
+ Project-URL: Documentation, https://github.com/Sriramdayal/LOOPENGT/tree/main/docs
7
+ Project-URL: Repository, https://github.com/Sriramdayal/LOOPENGT
8
+ Project-URL: Issues, https://github.com/Sriramdayal/LOOPENGT/issues
9
+ Author: Loop Engineering Contributors
10
+ License-Expression: GPL-3.0-or-later
11
+ License-File: LICENSE
12
+ Keywords: agent,ai,loop,mcp,orchestration
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: aiosqlite>=0.19
24
+ Requires-Dist: anyio>=4.0
25
+ Requires-Dist: pydantic<3.0,>=2.0
26
+ Requires-Dist: pyyaml>=6.0
27
+ Requires-Dist: rich>=13.0
28
+ Requires-Dist: structlog>=23.0
29
+ Requires-Dist: typer>=0.9
30
+ Provides-Extra: all
31
+ Requires-Dist: fastmcp>=0.1; extra == 'all'
32
+ Requires-Dist: httpx>=0.25; extra == 'all'
33
+ Requires-Dist: mcp>=1.0; extra == 'all'
34
+ Requires-Dist: mypy>=1.8; extra == 'all'
35
+ Requires-Dist: openai>=1.0; extra == 'all'
36
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'all'
37
+ Requires-Dist: pytest-cov>=4.0; extra == 'all'
38
+ Requires-Dist: pytest>=7.0; extra == 'all'
39
+ Requires-Dist: ruff>=0.4; extra == 'all'
40
+ Requires-Dist: types-aiofiles>=23.0; extra == 'all'
41
+ Requires-Dist: types-pyyaml>=6.0; extra == 'all'
42
+ Provides-Extra: antigravity
43
+ Provides-Extra: claude-code
44
+ Provides-Extra: codex
45
+ Provides-Extra: cursor
46
+ Provides-Extra: dev
47
+ Requires-Dist: mypy>=1.8; extra == 'dev'
48
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
49
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
50
+ Requires-Dist: pytest>=7.0; extra == 'dev'
51
+ Requires-Dist: ruff>=0.4; extra == 'dev'
52
+ Requires-Dist: types-aiofiles>=23.0; extra == 'dev'
53
+ Requires-Dist: types-pyyaml>=6.0; extra == 'dev'
54
+ Provides-Extra: llm
55
+ Requires-Dist: httpx>=0.25; extra == 'llm'
56
+ Requires-Dist: openai>=1.0; extra == 'llm'
57
+ Provides-Extra: mcp
58
+ Requires-Dist: fastmcp>=0.1; extra == 'mcp'
59
+ Requires-Dist: mcp>=1.0; extra == 'mcp'
60
+ Description-Content-Type: text/markdown
61
+
62
+ # LOOPENGT — Loop Engineering Agent
63
+
64
+
65
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
66
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
67
+
68
+ **Design, orchestrate, and evaluate agent loops** — a framework for building
69
+ production-grade multi-agent workflows with MCP integration and IDE-agnostic
70
+ plugin architecture.
71
+
72
+ ## Features
73
+
74
+ - 🔄 **5 orchestration patterns** — sequential, supervisor-worker, parallel
75
+ fan-out, handoff, evaluator-optimizer
76
+ - 🧩 **Plugin architecture** — extend with custom adapters, tools, templates. Includes built-in plugins for **Cursor, Claude Code, Antigravity, and Codex**.
77
+ - 🧠 **Native LLM Integration** — Built-in support for OpenAI and Hugging Face Inference Endpoints for autonomous loop orchestration.
78
+ - 🔌 **MCP server** — expose loop tools to Cursor, Claude Code, Antigravity
79
+ - 📊 **Built-in tracing** — SQLite + JSONL traces with OpenTelemetry export
80
+ - 🧪 **Evaluation framework** — built-in metrics + LLM-as-judge
81
+ - 📝 **5 built-in templates** — planner-executor, reviewer-retry,
82
+ supervisor-workers, research-architect, handoff loop
83
+ - ⚡ **Async-first** — built on anyio for concurrent execution
84
+
85
+ ## Quick Start
86
+
87
+ ```bash
88
+ # Create and activate a virtual environment
89
+ uv venv
90
+ .venv\Scripts\activate # On Windows
91
+ # source .venv/bin/activate # On macOS/Linux
92
+
93
+ # Install the base package
94
+ uv pip install loopengt
95
+
96
+ # With MCP support
97
+ uv pip install "loopengt[mcp]"
98
+
99
+ # With everything
100
+ uv pip install "loopengt[all]"
101
+ ```
102
+
103
+ ### Initialize
104
+
105
+ ```bash
106
+ loopengt init
107
+ ```
108
+
109
+ Creates a `.loopengt/` directory with configuration, templates, and prompts.
110
+
111
+ ### Design a Loop
112
+
113
+ ```bash
114
+ loopengt design "code review loop with automated testing"
115
+ ```
116
+
117
+ Generates `loop.yaml` and `LOOP_DESIGN.md`.
118
+
119
+ ### Execute
120
+
121
+ ```bash
122
+ loopengt run loop.yaml
123
+ ```
124
+
125
+ ### Inspect Traces
126
+
127
+ ```bash
128
+ loopengt trace <run_id>
129
+ ```
130
+
131
+ ### Evaluate
132
+
133
+ ```bash
134
+ loopengt eval <run_id>
135
+ ```
136
+
137
+ ## How to Engineer a Loop (Step-by-Step Guide)
138
+
139
+ Building an autonomous agent loop with LOOPENGT involves designing the architecture, defining the agents, and orchestrating their workflow. Here is the recommended workflow for engineering a new loop from scratch:
140
+
141
+ ### Step 1: Initialize Your Workspace
142
+ First, set up the necessary project configurations by running:
143
+ ```bash
144
+ loopengt init
145
+ ```
146
+ This scaffolds a `.loopengt/` directory in your project containing configuration files, built-in templates, and prompts.
147
+
148
+ ### Step 2: Set Your LLM Provider
149
+ Ensure your environment is configured for the LLM that will both design and run your agents. For example, to use OpenAI:
150
+ ```bash
151
+ export OPENAI_API_KEY="your-api-key"
152
+ export LOOPENGT_LLM_PROVIDER="openai"
153
+ ```
154
+
155
+ ### Step 3: Design the Loop
156
+ Instead of writing the YAML specification manually, use the built-in AI Architect to design the loop for you. Provide a clear goal:
157
+ ```bash
158
+ loopengt design "create a content generation loop where a Researcher finds facts, a Writer drafts an article, and an Editor reviews it for quality."
159
+ ```
160
+ The architect will generate two files:
161
+ - **`LOOP_DESIGN.md`**: A human-readable breakdown of the agents, their roles, and the orchestration strategy.
162
+ - **`loop.yaml`**: The executable Pydantic-serializable configuration file.
163
+
164
+ ### Step 4: Refine the Configuration (Optional)
165
+ Open `loop.yaml` in your editor. You can manually tweak:
166
+ - **Agents**: Adjust system prompts, input/output schemas, or LLM settings.
167
+ - **Tools**: Add native functions or MCP integrations.
168
+ - **Policies**: Set retry limits, turn budgets, or verification gates.
169
+
170
+ ### Step 5: Execute the Loop
171
+ Run the orchestrator using your generated specification:
172
+ ```bash
173
+ loopengt run loop.yaml
174
+ ```
175
+ Watch the terminal as the Executor coordinates the agents (Researcher -> Writer -> Editor) based on the chosen pattern (e.g., sequential or supervisor-worker).
176
+
177
+ ### Step 6: Trace and Evaluate
178
+ Once the run completes, inspect the detailed execution trace to debug or review agent interactions:
179
+ ```bash
180
+ # List recent runs to find the ID
181
+ ls .loopengt/runs/
182
+
183
+ # Inspect the trace
184
+ loopengt trace <run_id>
185
+ ```
186
+ If you want to score the quality of the final output, run the evaluator:
187
+ ```bash
188
+ loopengt eval <run_id>
189
+ ```
190
+
191
+ ## Architecture
192
+
193
+ ```
194
+ CLI / IDE Adapters → MCP Server → Plugin System → Core Runtime → Models
195
+
196
+ Tracing & Memory → Storage
197
+ ```
198
+
199
+ See [ARCHITECTURE.md](ARCHITECTURE.md) for details.
200
+
201
+ ## Orchestration Patterns
202
+
203
+ | Pattern | Description | Use Case |
204
+ |---------|-------------|----------|
205
+ | `sequential` | Steps execute in order | Simple workflows |
206
+ | `supervisor_worker` | Supervisor delegates to workers | Complex tasks |
207
+ | `parallel_fan_out` | Independent steps run concurrently | Batch processing |
208
+ | `handoff` | Agents pass enriched context along | Pipelines |
209
+ | `evaluator_optimizer` | Iterative quality improvement | Code review |
210
+
211
+ ## MCP Integration
212
+
213
+ Start the MCP server:
214
+
215
+ ```bash
216
+ loopengt mcp --transport stdio
217
+ ```
218
+
219
+ Add to Cursor (`.cursor/mcp.json`):
220
+
221
+ ```json
222
+ {
223
+ "mcpServers": {
224
+ "loopengt": {
225
+ "command": "loopengt",
226
+ "args": ["mcp", "--transport", "stdio"]
227
+ }
228
+ }
229
+ }
230
+ ```
231
+
232
+ ## CLI Commands
233
+
234
+ | Command | Description |
235
+ |---------|-------------|
236
+ | `loopengt init` | Scaffold .loopengt/ project directory |
237
+ | `loopengt design "goal"` | Design a loop from a goal |
238
+ | `loopengt run <spec>` | Execute a loop spec |
239
+ | `loopengt trace <id>` | Inspect execution trace |
240
+ | `loopengt eval <id>` | Run evaluations |
241
+ | `loopengt template list` | List available templates |
242
+ | `loopengt doctor` | Diagnose configuration |
243
+ | `loopengt mcp` | Start MCP server |
244
+
245
+ ## Development
246
+
247
+ ```bash
248
+ git clone https://github.com/Sriramdayal/LOOPENGT.git
249
+ cd LOOPENGT
250
+ uv pip install -e ".[dev]"
251
+
252
+
253
+ # Lint
254
+ ruff check src/ tests/
255
+
256
+ # Type check
257
+ mypy src/loopengt/
258
+
259
+ # Test
260
+ pytest tests/ -v
261
+ ```
262
+
263
+ ## Plugin Development
264
+
265
+ See [docs/plugin_dev.md](docs/plugin_dev.md) for the plugin development guide.
266
+
267
+ ## Examples
268
+
269
+ Check out the `examples/` directory for programmatic usage:
270
+ - `examples/basic_loop.py` — A simple sequential loop setup.
271
+ - `examples/multi_agent_loop.py` — A complex Supervisor-Worker multi-agent orchestration.
272
+
273
+ ## License
274
+
275
+ [GPL-3.0](LICENSE)