forge-agent-runtime 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.
@@ -0,0 +1,364 @@
1
+ Metadata-Version: 2.5
2
+ Name: forge-agent-runtime
3
+ Version: 0.1.0
4
+ Summary: Docker-isolated multi-agent orchestration runtime for the AgentForge ecosystem
5
+ Project-URL: Homepage, https://github.com/mhingan/forge-runtime
6
+ Project-URL: Repository, https://github.com/mhingan/forge-runtime
7
+ Project-URL: Issues, https://github.com/mhingan/forge-runtime/issues
8
+ Author: Mihaita Hingan
9
+ License: MIT License
10
+
11
+ Copyright (c) 2026 Mihaita Hingan
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26
+ License-File: LICENSE
27
+ Keywords: agentforge,agents,coding-agent,llm,multi-agent,orchestration
28
+ Classifier: Development Status :: 3 - Alpha
29
+ Classifier: Environment :: Console
30
+ Classifier: Intended Audience :: Developers
31
+ Classifier: License :: OSI Approved :: MIT License
32
+ Classifier: Operating System :: OS Independent
33
+ Classifier: Programming Language :: Python :: 3
34
+ Classifier: Programming Language :: Python :: 3.11
35
+ Classifier: Programming Language :: Python :: 3.12
36
+ Classifier: Programming Language :: Python :: 3.13
37
+ Classifier: Topic :: Software Development :: Build Tools
38
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
39
+ Requires-Python: >=3.11
40
+ Requires-Dist: agentforge-toolkit==1.1.0
41
+ Requires-Dist: httpx<1,>=0.27
42
+ Requires-Dist: pydantic-settings<3,>=2.2
43
+ Requires-Dist: pydantic<3,>=2.7
44
+ Requires-Dist: rich<15,>=13.7
45
+ Requires-Dist: typer<1,>=0.12
46
+ Provides-Extra: anthropic
47
+ Requires-Dist: anthropic<1,>=0.28; extra == 'anthropic'
48
+ Provides-Extra: api
49
+ Requires-Dist: fastapi<1,>=0.115; extra == 'api'
50
+ Requires-Dist: uvicorn[standard]<1,>=0.30; extra == 'api'
51
+ Provides-Extra: dev
52
+ Requires-Dist: mypy>=1.10; extra == 'dev'
53
+ Requires-Dist: pytest-asyncio<2,>=0.23; extra == 'dev'
54
+ Requires-Dist: pytest-cov<8,>=5; extra == 'dev'
55
+ Requires-Dist: pytest<9,>=8; extra == 'dev'
56
+ Requires-Dist: ruff>=0.5; extra == 'dev'
57
+ Provides-Extra: openai
58
+ Requires-Dist: openai<3,>=1.30; extra == 'openai'
59
+ Description-Content-Type: text/markdown
60
+
61
+ # Forge Runtime
62
+
63
+ **A provider-neutral execution and orchestration engine for the AgentForge ecosystem.**
64
+
65
+ Forge Runtime turns one user goal into a validated multi-agent execution graph. Forge Master selects specialist roles from AgentForge, asks an LLM provider to create a plan, validates the task dependencies, dispatches work concurrently, passes successful dependency results downstream, evaluates task outputs, and persists an execution history.
66
+
67
+ ## AgentForge integration
68
+
69
+ Forge Runtime depends on the published distribution **agentforge-toolkit 1.1.0**. The toolkit exposes its bundled library directory through `agentforge.core.data_root()`; the runtime reads the catalogs and Markdown definitions from that packaged data.
70
+
71
+ | Project | Responsibility |
72
+ |---|---|
73
+ | [AgentForge](https://github.com/mhingan/agent-forge) / [PyPI](https://pypi.org/project/agentforge-toolkit/1.1.0/) | Agent roles, skills, rules, workflows, catalogs, provider-specific coding-agent installation |
74
+ | **Forge Runtime** | Forge Master, planning, DAG scheduling, dispatch, model-provider calls, state, evaluation, API and execution reports |
75
+
76
+ The runtime does not call an undocumented AgentForge registry class or assume the toolkit is a hosted service. The adapter uses the package's real `data_root()` entry point. A local repository checkout and GitHub raw source are also supported.
77
+
78
+ ## Runtime capabilities
79
+
80
+ - **Forge Master:** central coordinator for each execution run.
81
+ - **AgentForge registry:** reads packaged roles, skills, rules and workflow playbooks.
82
+ - **Planning:** OpenAI and Anthropic providers produce a structured execution plan; mock provider supports deterministic smoke tests.
83
+ - **Task graph:** validates unique IDs, known roles/skills, dependencies, cycles and task limits before dispatch.
84
+ - **Parallel scheduler:** independent tasks run concurrently under a configurable semaphore.
85
+ - **Dependency context:** successful outputs are passed to tasks that depend on them.
86
+ - **Workspace tools:** OpenAI and Anthropic agents can list, read, search and (for `read-write` roles) write files in a configured project workspace.
87
+ - **Sandbox executor:** LLM agents can run tests, install dependencies and use the internet from disposable Docker containers with resource limits and controlled change-back.
88
+ - **Retries and deadlines:** bounded attempts and per-task timeouts.
89
+ - **Failure propagation:** tasks that depend on failed work are marked blocked.
90
+ - **Evaluation:** baseline output validation behind a replaceable evaluator contract.
91
+ - **Persistence:** SQLite records runs, task states, outputs and execution events.
92
+ - **CLI and HTTP API:** inspect the registry, submit work and inspect run history.
93
+
94
+ ## Architecture
95
+
96
+ ```text
97
+ User goal / CLI / HTTP API
98
+ |
99
+ v
100
+ FORGE MASTER
101
+ |
102
+ Load AgentForge toolkit data
103
+ |
104
+ LLM planner / Mock planner
105
+ |
106
+ Validate execution DAG
107
+ |
108
+ Task scheduler
109
+ / | \
110
+ v v v
111
+ Architect Backend Product ...
112
+ | | |
113
+ +----------+-----------+
114
+ |
115
+ Dependency result hand-off
116
+ |
117
+ Evaluator / Retry
118
+ |
119
+ SQLite store
120
+ |
121
+ Run report + event history
122
+ ```
123
+
124
+ AgentForge profiles and skills are untrusted model context, not executable permissions. OpenAI and Anthropic providers can modify ordinary files only inside `FORGE_WORKSPACE_ROOT`, and only when the selected role is `read-write`. Commands run inside Docker, never directly on the host. Git commit/push, browser, deployment and arbitrary MCP tools are not provided.
125
+
126
+ ## Requirements
127
+
128
+ - Python 3.11+
129
+ - AgentForge Toolkit 1.1.0 (installed automatically as a project dependency)
130
+ - An API key only when using OpenAI or Anthropic
131
+
132
+ ## Install from source
133
+
134
+ ```bash
135
+ git clone https://github.com/mhingan/forge-runtime.git
136
+ cd forge-runtime
137
+ python -m venv .venv
138
+ source .venv/bin/activate
139
+ python -m pip install -e ".[openai]"
140
+ ```
141
+
142
+ The dependency installation also installs `agentforge-toolkit==1.1.0`. No separate AgentForge clone is required for the standard configuration.
143
+
144
+
145
+ ## Install from PyPI
146
+
147
+ Once the first release is published:
148
+
149
+ ```bash
150
+ python -m pip install "forge-agent-runtime[openai]"
151
+ forge setup
152
+ forge run "Inspect this project, implement the requested feature and run the tests"
153
+ ```
154
+
155
+ For Anthropic, install `forge-agent-runtime[anthropic]`. The PyPI distribution is named `forge-agent-runtime`; the Python import package remains `forge_runtime`, and the command-line executable remains `forge`.
156
+
157
+ ## Quick start — two commands after installation
158
+
159
+ From the project directory, run:
160
+
161
+ ```bash
162
+ # Prompts for your OpenAI key, saves it safely in .env, and builds the Docker image
163
+ forge setup
164
+
165
+ # Give Forge a task; agents can edit files, install dependencies and access the internet
166
+ forge run "Inspect this project, implement the missing features and run the tests"
167
+ ```
168
+
169
+ Use `forge setup --provider anthropic` for Anthropic, or `forge setup --provider mock` for a no-key demo. Setup builds the sandbox image only once; later runs reuse it.
170
+
171
+ The sandbox uses Docker's `bridge` network by default, which enables outbound internet access for commands such as `curl`, `wget`, `pip install`, `npm install` and Git operations. Set `FORGE_SANDBOX_NETWORK=none` in `.env` to run offline.
172
+
173
+ ## First run — mock provider
174
+
175
+ ```bash
176
+ forge registry validate
177
+ forge agent list
178
+ forge skill list
179
+ forge rule list
180
+ forge workflow list
181
+
182
+ forge run "Design a secure REST API for an e-commerce platform" --provider mock
183
+ forge runs list
184
+ ```
185
+
186
+ Mock mode verifies registry loading, planning, graph validation, scheduling, persistence and event creation without making model API calls. Its outputs are clearly marked as demonstrations; it does not produce real code changes.
187
+
188
+ ## Run with an LLM
189
+
190
+ For OpenAI:
191
+
192
+ ```bash
193
+ export OPENAI_API_KEY="..."
194
+ export FORGE_DEFAULT_PROVIDER=openai
195
+ forge run "Build a secure customer management API with tests"
196
+ ```
197
+
198
+ Or choose a provider per run:
199
+
200
+ ```bash
201
+ forge run "Review the backend architecture" --provider openai
202
+ forge run "Plan a Flutter application" --provider anthropic
203
+ ```
204
+
205
+ Optional provider installs:
206
+
207
+ ```bash
208
+ python -m pip install -e ".[openai]"
209
+ python -m pip install -e ".[anthropic]"
210
+ ```
211
+
212
+ The LLM providers have bounded workspace and Docker command tools, but no direct host shell or deployment access. Their command execution runs in disposable containers.
213
+
214
+ ## Workspace access for coding tasks
215
+
216
+ OpenAI and Anthropic providers expose bounded workspace tools during specialist execution:
217
+
218
+ | Tool | Capability | AgentForge permission |
219
+ |---|---|---|
220
+ | `workspace_list_files` | List project files | read-only and read-write |
221
+ | `workspace_read_file` | Read UTF-8 source files | read-only and read-write |
222
+ | `workspace_search_files` | Search source text | read-only and read-write |
223
+ | `workspace_write_file` | Create or replace UTF-8 files | read-write only |
224
+ | `workspace_run_command` | Run allowlisted developer commands in isolated Docker | read-only and read-write |
225
+
226
+ The default workspace is the directory from which `forge` is launched. Set `FORGE_WORKSPACE_ROOT` to select a specific project. The runtime confines paths to that root and rejects traversal paths, drive-qualified paths, symlinks that escape the root, secret environment files and private-key files. It excludes common dependency/build directories and caps file sizes, search results, tool rounds and total tool calls.
227
+
228
+ Example:
229
+
230
+ ```bash
231
+ export FORGE_WORKSPACE_ROOT="/path/to/my-project"
232
+ export OPENAI_API_KEY="..."
233
+ forge run "Inspect the project, implement a responsive settings page, and add tests" --provider openai
234
+ ```
235
+
236
+ The model can read and write files through workspace tools. Command execution is a separate Docker capability described below. Mock mode never modifies files. Review the resulting diff before using changes in production.
237
+
238
+ ## Sandboxed command execution
239
+
240
+ Install and start Docker Desktop or Docker Engine. The first setup builds a local toolchain image and verifies that the sandbox can reach the internet.
241
+
242
+ ```bash
243
+ # Check the Docker daemon and configured image
244
+ forge sandbox check
245
+
246
+ # Build forge-runtime-sandbox:internet-v1 once
247
+ forge sandbox build
248
+
249
+ # Smoke-test the image
250
+ forge sandbox run -- python --version
251
+ forge sandbox run -- pytest --version
252
+
253
+ # Run the project's tests in a disposable container
254
+ forge sandbox run -- python -m pytest
255
+ ```
256
+
257
+ The LLM providers expose `workspace_run_command`. The tool accepts an argv array, not a raw shell string. Typical commands include `python -m pytest`, `ruff check .`, `mypy`, `npm test`, `node --test` and `make test`. Shells (`bash`/`sh`) are available inside the container for project scripts, but never on the host.
258
+
259
+ The sandbox uses Docker bridge networking for internet access, a read-only container root filesystem, dropped Linux capabilities, `no-new-privileges`, a non-root UID, PID/CPU/memory limits, an execution timeout and capped output. It receives a sanitized temporary copy of the project, excluding `.git`, environment secrets, credentials, private keys, dependency folders and common build caches. With internet enabled, `node_modules` is a temporary writable volume for package installation; in offline mode, an existing local `node_modules` may be mounted read-only. No host API keys or environment variables are forwarded.
260
+
261
+ For AgentForge `read-write` roles, newly created or modified regular files are copied back after the command. Deletions and symlinks are not copied back. For `read-only` roles, all container changes are discarded. A failed test command still returns stdout, stderr and its exit code so the agent can diagnose, fix and rerun.
262
+
263
+ The default image includes Python, pytest, Ruff, mypy, Node.js/npm, Git and common build tools. Projects requiring additional Python, Node or system libraries should customize `src/forge_runtime/sandbox_assets/Dockerfile`, rebuild the image and set `FORGE_SANDBOX_IMAGE` if using a different tag. Runtime containers never pull missing images automatically; run `forge sandbox build` explicitly.
264
+
265
+ Set `FORGE_SANDBOX_ENABLED=false` to remove command execution from model tool schemas. This is a Docker container boundary, not a VM: run Docker Engine on a trusted host, keep it patched and review agent changes before merging.
266
+
267
+ ## Registry source selection
268
+
269
+ The default setting `FORGE_AGENTFORGE_SOURCE=auto` loads the packaged AgentForge data via `agentforge.core.data_root()`.
270
+
271
+ | Setting | Behavior |
272
+ |---|---|
273
+ | `auto` | Use installed toolkit; fall back to GitHub when it is unavailable |
274
+ | `installed` | Require installed `agentforge-toolkit` package data |
275
+ | `local` | Use `FORGE_AGENTFORGE_LOCAL_PATH` |
276
+ | `github` | Fetch catalogs and referenced Markdown from the configured GitHub ref |
277
+
278
+ For a local AgentForge checkout:
279
+
280
+ ```bash
281
+ export FORGE_AGENTFORGE_SOURCE=local
282
+ export FORGE_AGENTFORGE_LOCAL_PATH="../agent-forge"
283
+ forge registry validate
284
+ ```
285
+
286
+ ## Local HTTP API
287
+
288
+ Install the API extra and start the service:
289
+
290
+ ```bash
291
+ python -m pip install -e ".[api]"
292
+ forge serve
293
+ ```
294
+
295
+ Default address: `http://127.0.0.1:8787`. Interactive API documentation is available at `/docs`.
296
+
297
+ | Method | Endpoint | Description |
298
+ |---|---|---|
299
+ | GET | `/health` | Service health |
300
+ | GET | `/v1/agents` | AgentForge agent catalog |
301
+ | GET | `/v1/skills` | AgentForge skill catalog |
302
+ | POST | `/v1/runs` | Submit a goal and execute the run |
303
+ | GET | `/v1/runs` | List recent runs |
304
+ | GET | `/v1/runs/{run_id}` | Read run, task and event records |
305
+
306
+ Example:
307
+
308
+ ```bash
309
+ curl http://127.0.0.1:8787/v1/agents
310
+
311
+ curl -X POST http://127.0.0.1:8787/v1/runs \
312
+ -H "Content-Type: application/json" \
313
+ -d '{"goal":"Plan a secure inventory API","provider":"mock"}'
314
+ ```
315
+
316
+ The API executes a submitted run synchronously and returns the final run record. This is a local control API, not yet a durable background job service. Keep it bound to localhost for personal development. For a network bind, set a strong `FORGE_API_TOKEN`; send it as `X-Forge-API-Key`.
317
+
318
+ ## Configuration
319
+
320
+ See `.env.example` and [the PyPI publishing guide](docs/publishing.md).
321
+
322
+ | Variable | Purpose | Default |
323
+ |---|---|---|
324
+ | `FORGE_DEFAULT_PROVIDER` | Default model provider | `mock` |
325
+ | `FORGE_MAX_PARALLEL_TASKS` | Max concurrent tasks | `4` |
326
+ | `FORGE_TASK_TIMEOUT_SECONDS` | Per-task timeout ceiling | `900` |
327
+ | `FORGE_DATABASE_URL` | SQLite database URL | `sqlite:///./.forge/forge.db` |
328
+ | `FORGE_WORKSPACE_ROOT` | Project directory visible to the runtime | `.` |
329
+ | `FORGE_SANDBOX_ENABLED` | Expose Docker command tool to LLM agents | `true` |
330
+ | `FORGE_SANDBOX_IMAGE` | Prebuilt local Docker image name | `forge-runtime-sandbox:internet-v1` |
331
+ | `FORGE_SANDBOX_NETWORK` | Sandbox network (`bridge` or `none`) | `bridge` |
332
+ | `FORGE_SANDBOX_CPU_LIMIT` / `MEMORY_MB` | Per-container CPU and memory limits | `2` / `2048` |
333
+ | `FORGE_SANDBOX_DEFAULT_TIMEOUT_SECONDS` | Default command timeout | `180` |
334
+ | `FORGE_AGENTFORGE_SOURCE` | Registry source selection | `auto` |
335
+ | `OPENAI_API_KEY` | OpenAI key | unset |
336
+ | `ANTHROPIC_API_KEY` | Anthropic key | unset |
337
+ | `FORGE_API_TOKEN` | HTTP API key for network binds | unset |
338
+
339
+ ## Security and limitations
340
+
341
+ - All user goals, registry files and model outputs are treated as untrusted content.
342
+ - Plans are validated against installed AgentForge role and skill names before any task runs.
343
+ - The scheduler enforces bounded concurrency, retries and timeouts.
344
+ - OpenAI and Anthropic agents can change ordinary files only inside `FORGE_WORKSPACE_ROOT` and only with a `read-write` role; secrets are excluded from workspace tools and sandbox snapshots.
345
+ - Shell/test/build commands run only inside ephemeral Docker containers. Bridge mode provides outbound internet and may reach private/LAN destinations accessible from the Docker host. Use `none` for offline tasks. This is container isolation, not a VM or protection from host-kernel/Docker-daemon vulnerabilities.
346
+ - The sandbox does not provide Git commit/push, deployment, browser access or arbitrary MCP tools. Deletions are not copied back.
347
+ - Tasks flagged as requiring human approval are rejected because the approval subsystem is not enabled yet.
348
+ - SQLite is intended for local and single-process use; it is not a distributed job queue.
349
+ - The baseline evaluator checks output presence and size; it is not a semantic correctness guarantee.
350
+ - The HTTP API should not be exposed publicly without a hardened deployment, authentication, TLS and tenant isolation.
351
+
352
+ ## Development
353
+
354
+ ```bash
355
+ python -m pip install -e ".[dev,api]"
356
+ pytest
357
+ ruff check . --fix && ruff check .
358
+ ```
359
+
360
+ See [architecture](docs/architecture.md), [provider contracts](docs/providers.md), [sandbox details](docs/sandbox.md), [security](docs/security.md), [roadmap](ROADMAP.md) and [contributing](CONTRIBUTING.md).
361
+
362
+ ## License
363
+
364
+ MIT.
@@ -0,0 +1,25 @@
1
+ forge_runtime/__init__.py,sha256=uzGnG4FbdHGEWjkVquImoARA8AF4-usCgUzWIM6sYZA,656
2
+ forge_runtime/api.py,sha256=OESanpWFJeIhctiBTp4XXFaUf9j3nmyxwkn94ferM7c,4675
3
+ forge_runtime/cli.py,sha256=HtL8uRb6qCp12GPqGBIILNUmxR_a_oXGCPjraEeCeCM,14734
4
+ forge_runtime/config.py,sha256=qZabx3nz8OPaRMe2kG-XqNuCZefa4vm3N8zNO-_i4Sw,2195
5
+ forge_runtime/evaluation.py,sha256=3rvJE6EPoHTeI82qLVVFnJJrJpRIDyY2Xrls6MG2ttA,726
6
+ forge_runtime/graph.py,sha256=6mIwOdAruTRGe23qslu6Ee9Ctt7LU1dadryjC81nGxc,2922
7
+ forge_runtime/models.py,sha256=aXUsWOuBVgus_Ft1Oxoti-uoETlC79K1EWEA1d640XY,3529
8
+ forge_runtime/orchestrator.py,sha256=_q3gGd-m6OkSmZk-GjHp2X7bH3pmEoFZN2OODCmEwfs,11890
9
+ forge_runtime/registry.py,sha256=Sg8d7C19nOFDSwE8EPrNyUYuWyoyySEZhX4RH_Y9-Xk,10466
10
+ forge_runtime/sandbox.py,sha256=JT9wM7YB4lZgSTxeT4Hkj09RmaQrqvrT0YDSqRsg7EQ,37644
11
+ forge_runtime/storage.py,sha256=ctViXZ4fKxq5d2Yqhbc7XuzwBRepRpzt9ugPBPSJbRY,4228
12
+ forge_runtime/workspace.py,sha256=gwmQjy_LissW6H3cUmnNQ3qBxsXPImqRnfE19HrE62Q,12543
13
+ forge_runtime/providers/__init__.py,sha256=slHNb94H6kLyUibHZkTYkhrtVv0S4MXW29892XJ2jwU,35
14
+ forge_runtime/providers/anthropic_provider.py,sha256=LANfUE0r8ITo1TC1xIs-4I52anyYtTGRkRbVkERy1bk,10492
15
+ forge_runtime/providers/base.py,sha256=xTssjgbIkghth8vBl0HSfPsGnjFM_ryTQfdFOYg01lo,394
16
+ forge_runtime/providers/factory.py,sha256=51JtrrnCsB-PDtZULar0HjKfxa33rq0Ll0vuJOK_2zM,1981
17
+ forge_runtime/providers/mock.py,sha256=11hgq1tfGARv8iPNthXjE-qJEh0IROcrDnXqNs5bQ9Q,1864
18
+ forge_runtime/providers/openai_provider.py,sha256=L4s7Dcv8kaBjbzSL1pcLtdbJYd-JwvxqDl2PNeAz_FM,11552
19
+ forge_runtime/sandbox_assets/__init__.py,sha256=1DtyJxsY2Ax3GNWLVs2N-z5rFJm3RODrxZ8Y18W-UV8,66
20
+ forge_runtime/sandbox_assets/Dockerfile,sha256=kWKehULCDMtHPt2xxK4ZPG5G3FDI8gDPfZcRuagKijk,1296
21
+ forge_agent_runtime-0.1.0.dist-info/METADATA,sha256=dKUOUezw9NGoGQP9ENc2lsaIKoeMEp3L5ZK5fKtIXVY,17957
22
+ forge_agent_runtime-0.1.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
23
+ forge_agent_runtime-0.1.0.dist-info/entry_points.txt,sha256=cwgQpbGT9zauIxxKwKDny5PEqBX-aOSp2giriKKe4_k,48
24
+ forge_agent_runtime-0.1.0.dist-info/licenses/LICENSE,sha256=DjMXvPnWtt0Iq8cSxPaicC7SGTQVV1DEUpGECqqtmB8,812
25
+ forge_agent_runtime-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.33.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ forge = forge_runtime.cli:app
@@ -0,0 +1,17 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mihaita Hingan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -0,0 +1,32 @@
1
+ """Forge Runtime public package interface."""
2
+ from forge_runtime.models import (
3
+ AgentDefinition,
4
+ AgentRequest,
5
+ AgentResult,
6
+ ExecutionPlan,
7
+ RunRecord,
8
+ RunStatus,
9
+ SkillDefinition,
10
+ TaskSpec,
11
+ TaskStatus,
12
+ )
13
+ from forge_runtime.orchestrator import ForgeMaster
14
+ from forge_runtime.registry import AgentForgeRegistry, RegistryError
15
+
16
+ __version__ = "0.1.0"
17
+
18
+ __all__ = [
19
+ "AgentDefinition",
20
+ "AgentForgeRegistry",
21
+ "AgentRequest",
22
+ "AgentResult",
23
+ "ExecutionPlan",
24
+ "ForgeMaster",
25
+ "RegistryError",
26
+ "RunRecord",
27
+ "RunStatus",
28
+ "SkillDefinition",
29
+ "TaskSpec",
30
+ "TaskStatus",
31
+ "__version__",
32
+ ]
forge_runtime/api.py ADDED
@@ -0,0 +1,139 @@
1
+ """Optional local HTTP API for submitting and inspecting Forge runs."""
2
+ from __future__ import annotations
3
+
4
+ import secrets
5
+ from ipaddress import ip_address
6
+ from typing import Annotated, Any
7
+
8
+ from fastapi import Depends, FastAPI, Header, HTTPException, Request
9
+ from pydantic import BaseModel, Field
10
+
11
+ from forge_runtime import __version__
12
+ from forge_runtime.config import Settings
13
+ from forge_runtime.orchestrator import ForgeMaster
14
+ from forge_runtime.providers.factory import create_provider
15
+ from forge_runtime.registry import AgentForgeRegistry, RegistryError
16
+ from forge_runtime.storage import SQLiteStore
17
+
18
+ settings = Settings()
19
+ app = FastAPI(
20
+ title="Forge Runtime API",
21
+ version=__version__,
22
+ description="Local API for AgentForge-backed multi-agent orchestration.",
23
+ )
24
+
25
+
26
+ class CreateRunRequest(BaseModel):
27
+ goal: str = Field(min_length=1, max_length=20_000)
28
+ provider: str | None = None
29
+
30
+
31
+ def authorize(
32
+ request: Request,
33
+ x_forge_api_key: Annotated[str | None, Header()] = None,
34
+ ) -> None:
35
+ """Require a token for non-loopback clients, regardless of the server bind address."""
36
+ if settings.api_token:
37
+ if not x_forge_api_key or not secrets.compare_digest(
38
+ x_forge_api_key, settings.api_token
39
+ ):
40
+ raise HTTPException(status_code=401, detail="Invalid or missing Forge API key.")
41
+ return
42
+
43
+ client_host = request.client.host if request.client is not None else ""
44
+ try:
45
+ is_loopback = ip_address(client_host).is_loopback
46
+ except ValueError:
47
+ is_loopback = False
48
+ if not is_loopback:
49
+ raise HTTPException(
50
+ status_code=401,
51
+ detail="Set FORGE_API_TOKEN and send X-Forge-API-Key for non-local access.",
52
+ )
53
+
54
+
55
+ def get_store() -> SQLiteStore:
56
+ return SQLiteStore(settings.database_url)
57
+
58
+
59
+ def get_registry() -> AgentForgeRegistry:
60
+ return AgentForgeRegistry(
61
+ local_path=settings.agentforge_local_path,
62
+ repository=settings.agentforge_repository,
63
+ ref=settings.agentforge_ref,
64
+ source=settings.agentforge_source,
65
+ )
66
+
67
+
68
+ def get_runtime(provider_name: str | None = None) -> ForgeMaster:
69
+ registry = get_registry()
70
+ provider = create_provider(provider_name or settings.default_provider, settings)
71
+ return ForgeMaster(registry=registry, provider=provider, settings=settings)
72
+
73
+
74
+ @app.get("/health", dependencies=[Depends(authorize)])
75
+ def health() -> dict[str, str]:
76
+ return {"status": "ok", "service": "forge-runtime", "version": __version__}
77
+
78
+
79
+ @app.get("/v1/agents", dependencies=[Depends(authorize)])
80
+ def list_agents() -> list[dict[str, Any]]:
81
+ try:
82
+ registry = get_registry()
83
+ registry.load()
84
+ except RegistryError as exc:
85
+ raise HTTPException(status_code=503, detail=str(exc)) from exc
86
+ return [
87
+ {
88
+ "name": agent.name,
89
+ "description": agent.description,
90
+ "mode": agent.mode,
91
+ "recommended_skills": list(agent.recommended_skills),
92
+ }
93
+ for agent in registry.agents.values()
94
+ ]
95
+
96
+
97
+ @app.get("/v1/skills", dependencies=[Depends(authorize)])
98
+ def list_skills() -> list[dict[str, str]]:
99
+ try:
100
+ registry = get_registry()
101
+ registry.load()
102
+ except RegistryError as exc:
103
+ raise HTTPException(status_code=503, detail=str(exc)) from exc
104
+ return [
105
+ {"name": skill.name, "description": skill.description, "path": skill.path}
106
+ for skill in registry.skills.values()
107
+ ]
108
+
109
+
110
+ @app.post("/v1/runs", status_code=201, dependencies=[Depends(authorize)])
111
+ async def create_run(payload: CreateRunRequest) -> dict[str, Any]:
112
+ try:
113
+ runtime = get_runtime(payload.provider)
114
+ run = await runtime.execute(payload.goal)
115
+ return run.model_dump(mode="json")
116
+ except RegistryError as exc:
117
+ raise HTTPException(status_code=503, detail=str(exc)) from exc
118
+ except ValueError as exc:
119
+ raise HTTPException(status_code=400, detail=str(exc)) from exc
120
+ except Exception as exc:
121
+ raise HTTPException(
122
+ status_code=502,
123
+ detail=f"Orchestration failed: {type(exc).__name__}: {exc}",
124
+ ) from exc
125
+
126
+
127
+ @app.get("/v1/runs", dependencies=[Depends(authorize)])
128
+ def list_runs(limit: int = 20) -> list[dict[str, Any]]:
129
+ if limit < 1 or limit > 100:
130
+ raise HTTPException(status_code=422, detail="limit must be between 1 and 100.")
131
+ return get_store().list_runs(limit)
132
+
133
+
134
+ @app.get("/v1/runs/{run_id}", dependencies=[Depends(authorize)])
135
+ def get_run(run_id: str) -> dict[str, Any]:
136
+ run = get_store().get_run(run_id)
137
+ if run is None:
138
+ raise HTTPException(status_code=404, detail="Run not found.")
139
+ return run