Skip to content

feat(engine-api): add FastAPI reference adapter and /policies gap-fix (Epic 0, issue #3066) - #3085

Merged
Ricky Gummadi (Ricky-G) merged 52 commits into
mainfrom
ricky-g/issue-3066-engine-api-fastapi-adapter
Jul 30, 2026
Merged

Ricky Gummadi (Ricky-G) merged 52 commits into
mainfrom
ricky-g/issue-3066-engine-api-fastapi-adapter

Conversation

@Ricky-G

Copy link
Copy Markdown
Contributor

Summary

Stand up the reference FastAPI adapter for the AGT Studio Engine API contract: one app, one process, one OpenAPI document exposing all 12 v1 HTTP operations (11 read-only plus the single mutating POST /api/v1/policy/save), each decorated with the capability_flags library from PR #3027. Also fixes the long-standing counts-only gap on GET /api/v1/policies so it returns paginated PolicySummary objects instead of a totals dict.

Problem

The Engine API contract (docs/studio/engine-api-contract.md) and its machine-readable companion (docs/studio/openapi.yaml) had no reference server implementation. Studio panels in later epics need one URL that discovers the entire surface with x-capability-flags on every operation. Separately, agentmesh.server.policy_server only returned counts for GET /api/v1/policies, not the per-policy summaries the contract requires.

Changes

Path What changed
engine_api/app.py New create_app(policy_dir=None) factory: resolves the policy dir (arg, then AGENTMESH_POLICY_DIR, then default), wires the error envelope, includes every route module, and applies inject_capability_extension last.
engine_api/__init__.py Lazy create_app export via PEP 562 __getattr__ so the capability library stays importable without FastAPI installed.
engine_api/__main__.py CLI entry point (python -m agentmesh.engine_api) running uvicorn, default bind 127.0.0.1:8080 (loopback only).
engine_api/errors.py Section 10 error envelope, the full section 10.3 code set, and handlers that remap RequestValidationError and unhandled exceptions to the envelope shape.
engine_api/pagination.py PaginationParams dependency (page >= 1 default 1, limit 1..100 default 20) and the Pagination response model.
engine_api/models.py Pydantic request/response models with section 7 field names. Timestamp fields are typed datetime so the generated OpenAPI emits format: date-time.
engine_api/policy_registry.py Filesystem-backed registry for the policy read/write routes. save() validates the resolved target stays inside the policy directory.
engine_api/routes/policies.py GET /api/v1/policies (paginated summaries, the gap fix) and GET /api/v1/policies/{id} (404 POLICY_NOT_FOUND).
engine_api/routes/policy_ops.py validatePolicy, testPolicy, and savePolicy (the only mutating op; persists then reloads).
engine_api/routes/{health,versions,audit,trust,agents,decisions}.py Health, version info, and the spec-conformant empty placeholder surfaces for backends owned by later epics.
tests/engine_api/* 14 test modules plus shared fixtures covering the app factory, OpenAPI/capability wiring, error envelope, pagination, the policy registry, and every route group.

Testing

  • pytest agent-governance-python/agent-mesh/tests/engine_api/: 136 passed.
  • ruff check --select E,F,W --ignore E501 on changed files: clean. Full package config (E, F, I, N, W, UP) also clean.
  • Coverage on the new package: 99% overall, with every new module at 100% (the only misses are pre-existing openapi.py lines from PR feat(engine-api): add capability-metadata library for AGT Studio #3027).
  • A rubber-duck review by a second model (GPT-5.4) was run against the contract. Its findings drove the {id} path parameter rename, the date-time typing, and the save() path-traversal guard.

Follow-ups (intentionally out of scope here)

  • /api/v1/events is explicitly deferred to Epic 7a (issue build(deps-dev): Bump eslint from 8.57.1 to 10.0.2 in /packages/agent-os/extensions/copilot #16) per this issue's Scope (out): not implemented, registered, or stubbed. The contract's 426 Upgrade Required behavior for that reserved path lands with the WebSocket work.
  • The adapter's generated OpenAPI documents FastAPI's default HTTPValidationError for 422 rather than the section 10 envelope, and does not enumerate per-operation 4XX/5XX error responses. Runtime behavior already returns the envelope for every error; aligning the generated schema with the envelope is a documentation-only refinement worth a separate change.

Closes #3066.

Stand up the reference FastAPI adapter for the AGT Studio Engine API
contract: a create_app() factory exposing the 12 v1 HTTP operations
(11 read-only plus POST /api/v1/policy/save), each carrying capability
flags, the section 10 error envelope, section 11 pagination, a
filesystem-backed policy registry, and a loopback-only CLI entry point.
Fixes the counts-only gap on GET /api/v1/policies by returning paginated
PolicySummary objects.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
@github-actions

github-actions Bot commented Jun 16, 2026 •

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions github-actions Bot added tests agent-mesh agent-mesh package size/XL Extra large PR (500+ lines) and removed tests agent-mesh agent-mesh package labels Jun 16, 2026
@github-actions

github-actions Bot commented Jun 16, 2026 •

Copy link
Copy Markdown
🤖 AI Agent: security-scanner — View details

AI-generated review output. Treat it as untrusted analysis and verify before acting.

No security issues found.

@github-actions

github-actions Bot commented Jun 16, 2026 •

Copy link
Copy Markdown
🤖 AI Agent: breaking-change-detector — API Compatibility

AI-generated review output. Treat it as untrusted analysis and verify before acting.

API Compatibility

Severity Change Impact
High GET /api/v1/policies now returns paginated PolicySummary objects instead of a totals dictionary. Existing clients relying on the previous response format will break.
High POST /api/v1/policy/save is disabled by default unless explicitly enabled via CLI flag or environment variable. Existing deployments expecting this endpoint to be enabled by default will encounter 403 FORBIDDEN.
Medium create_app is now lazily imported via __getattr__ in engine_api/__init__.py. Code relying on direct imports of create_app may encounter unexpected behavior if not updated.

@github-actions

github-actions Bot commented Jun 16, 2026 •

Copy link
Copy Markdown
🤖 AI Agent: code-reviewer — View details

AI-generated review output. Treat it as untrusted analysis and verify before acting.

TL;DR: 0 blockers, 1 warning. Solid implementation with minor follow-up needed.

# Sev Issue Where
1 W Generated OpenAPI schema does not align with runtime error envelope behavior. engine_api/app.py

Action items: None (no blockers).

Warnings:

# Issue Fine as follow-up PRs
1 Align OpenAPI schema with runtime error envelope for 4XX/5XX responses. Yes

@github-actions

github-actions Bot commented Jun 16, 2026 •

Copy link
Copy Markdown
🤖 AI Agent: test-generator — `agentmesh/engine_api/app.py`

AI-generated review output. Treat it as untrusted analysis and verify before acting.

agentmesh/engine_api/app.py

  • test_create_app_with_default_policy_dir -- Test create_app with no policy_dir argument to ensure it defaults to AGENTMESH_POLICY_DIR or DEFAULT_POLICY_DIR.
  • test_create_app_with_policy_save_disabled -- Test create_app with enable_policy_save set to None and the environment variable AGENTMESH_ENABLE_POLICY_SAVE unset or set to a non-truthy value.
  • test_create_app_with_policy_save_enabled -- Test create_app with enable_policy_save explicitly set to True and verify POST /api/v1/policy/save is enabled.

agentmesh/engine_api/__main__.py

  • test_main_with_default_args -- Test the main function with default arguments to ensure it starts the app on 127.0.0.1:8080.
  • test_main_with_custom_args -- Test the main function with custom --host, --port, and --policy-dir arguments.

agentmesh/engine_api/errors.py

  • test_register_error_handlers -- Verify that register_error_handlers correctly registers handlers for RequestValidationError and unhandled exceptions.
  • test_error_envelope_format -- Test that all errors conform to the section 10.2 envelope format.
  • test_forbidden_error -- Validate that POST /api/v1/policy/save returns a 403 FORBIDDEN error when policy saving is disabled.

@github-actions

github-actions Bot commented Jun 16, 2026 •

Copy link
Copy Markdown
🤖 AI Agent: docs-sync-checker — Docs Sync

AI-generated review output. Treat it as untrusted analysis and verify before acting.

Docs Sync

  • docs/studio/engine-api-contract.md -- outdated due to the addition of the FastAPI reference adapter and the /policies gap fix.
  • docs/studio/openapi.yaml -- outdated due to changes in the API behavior and new endpoints.
  • CHANGELOG.md -- missing entry for the introduction of the FastAPI reference adapter and the /policies gap fix.

@github-actions

Copy link
Copy Markdown

🟡 Contributor Check: MEDIUM

Check Result
Profile MEDIUM
Credential LOW
Overall MEDIUM

Automated check by AGT Contributor Check.

@github-actions github-actions Bot added the needs-review:MEDIUM Contributor check flagged MEDIUM risk label Jun 16, 2026
@github-actions

github-actions Bot commented Jun 16, 2026 •

Copy link
Copy Markdown

PR Review Summary

Check Status Details
🔍 Code Review ⚠️ Missing No current-run comment
🛡️ Security Scan ⚠️ Missing No current-run comment
🔄 Breaking Changes ⚠️ Missing No current-run comment
📝 Docs Sync ⚠️ Missing No current-run comment
🧪 Test Coverage ⚠️ Missing No current-run comment

Verdict: ⚠️ AI review incomplete; ready for human review

AI review comments are untrusted advisory output. The summary reports workflow-generated completion status only, not model-authored pass/fail claims.

@github-actions github-actions Bot added tests agent-mesh agent-mesh package labels Jun 16, 2026
@Ricky-G Ricky Gummadi (Ricky-G) changed the title feat(engine-api): FastAPI reference adapter and /policies gap-fix (Epic 0, issue #3066) feat: FastAPI reference adapter and /policies gap-fix (Epic 0, issue #3066) Jun 16, 2026
Comment thread agent-governance-python/agent-mesh/tests/engine_api/test_app.py Fixed
Comment thread agent-governance-python/agent-mesh/tests/engine_api/test_app.py Fixed
Comment thread agent-governance-python/agent-mesh/tests/engine_api/test_app.py Fixed
@Ricky-G Ricky Gummadi (Ricky-G) changed the title feat: FastAPI reference adapter and /policies gap-fix (Epic 0, issue #3066) feat(engine-api): add FastAPI reference adapter and /policies gap-fix (Epic 0, issue #3066) Jun 16, 2026
Ricky Gummadi (Ricky-G) and others added 7 commits June 17, 2026 11:20
Remove TODO markers from the placeholder route docstrings (the
no-stubs gate forbids them), reword them as plain prose that points
to the later epic. Replace the test fixture string
otanumber and
the word Indirected so the spell-check passes, and register
starlette in the cspell dictionary.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
…astAPI 0.118+

FastAPI 0.118+/Starlette 1.x stopped flattening include_router() sub-routes into app.router.routes, wrapping them in an _IncludedRouter proxy instead. inject_capability_extension iterates app.routes for top-level APIRoute instances, so every operation was silently skipped (no x-capability-flags, empty Studio allowlist) under the newer FastAPI used in CI. Register each route module's APIRoute objects directly on the app so they stay visible to the capability hook across all supported FastAPI versions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
… root

The POST /api/v1/policy/test route forwarded the request-supplied policy_dir straight into the file-reading replay engine, which CodeQL flagged as py/path-injection (the override could steer the engine at arbitrary server paths). Resolve the override and the configured policy root to real absolute paths and require the override to stay within that root via os.path.commonpath, raising 422 FIXTURE_LOAD_ERROR otherwise. Update the two tests that relied on out-of-root overrides to use in-root directories and add a rejection test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
Both are standard-library identifiers (os.path.commonpath, tmp_path_factory.mktemp) introduced by the policy_dir containment guard and its tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
…ride

The commonpath-based guard cleared the runtime risk but CodeQL still traced the request body into the replay sink because the guard was an indirect boolean. Switch to the recognized path-traversal sanitizer: return the untainted engine root for the equality case and guard the subdirectory return with a direct realpath startswith check, which breaks the py/path-injection data flow.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
…ed-import findings

The package-level agentmesh import and the two agentmesh.engine_api imports in TestPackageExports were flagged as unused. Convert them to importlib.import_module calls so the side effect (firing the package deprecation warning once before create_app is wrapped) is preserved without binding an unused import name.

Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ricky Gummadi (Ricky-G) and others added 5 commits July 26, 2026 20:35
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
Copilot AI review requested due to automatic review settings July 26, 2026 08:36
@Ricky-G
Ricky Gummadi (Ricky-G) force-pushed the ricky-g/issue-3066-engine-api-fastapi-adapter branch from 83b945e to a99e7dc Compare July 26, 2026 08:36
@github-actions github-actions Bot added documentation Improvements or additions to documentation integration/mastra-agentmesh scripts/ci/cd labels Jul 26, 2026
@github-actions

Copy link
Copy Markdown

📦 Dependency diff (SBOM)

Comparing main → ricky-g/issue-3066-engine-api-fastapi-adapter.

✅ No dependency changes detected.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 71 out of 74 changed files in this pull request and generated 3 comments.

Files not reviewed (3)
  • agent-governance-python/agent-mesh/packages/mcp-proxy/package-lock.json: Generated file
  • agent-governance-python/agent-os/extensions/mcp-server/package-lock.json: Generated file
  • agent-governance-python/agentmesh-integrations/mastra-agentmesh/package-lock.json: Generated file

Comment thread agent-governance-python/agt-policies/src/agt/policies/result.py
Comment thread agent-governance-python/agent-mesh/src/agentmesh/engine_api/policy_registry.py Outdated
Comment thread docs/v4-removal.md
Ricky Gummadi (Ricky-G) and others added 3 commits July 26, 2026 20:49
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1523e5b8-938c-415c-a8ad-52be4cbda287
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1523e5b8-938c-415c-a8ad-52be4cbda287
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1523e5b8-938c-415c-a8ad-52be4cbda287
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
Copilot AI review requested due to automatic review settings July 26, 2026 08:52
@Ricky-G
Ricky Gummadi (Ricky-G) force-pushed the ricky-g/issue-3066-engine-api-fastapi-adapter branch from a99e7dc to 75135bc Compare July 26, 2026 08:52
@github-actions github-actions Bot removed documentation Improvements or additions to documentation integration/mastra-agentmesh scripts/ci/cd labels Jul 26, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

agent-governance-python/agent-mesh/src/agentmesh/engine_api/routes/policies.py:9

  • The PR description says it fixes the counts-only gap on agentmesh.server.policy_server's GET /api/v1/policies, but this PR only adds the corrected paginated behavior in the new Engine API reference adapter. In the current tree, agentmesh/server/policy_server.py still returns a totals dict for /api/v1/policies.

Either (a) update the PR description (and/or issue scope) to clarify the gap is fixed via the new reference adapter only, or (b) include the legacy policy_server.py change in this PR (if that is still a requirement).

``GET /api/v1/policies`` returns a paginated list of :class:`PolicySummary` objects.
This reference adapter implements the contract shape; the legacy
``agentmesh.server.policy_server`` endpoint still returns totals only.
``GET /api/v1/policies/{id}`` returns full :class:`PolicyDetail` or a
``POLICY_NOT_FOUND`` envelope.

@Ricky-G

Copy link
Copy Markdown
Contributor Author

MohammadHaroonAbuomar Thank you for the review. The seven Autofix commits now have DCO signoffs, all follow-up findings are addressed, and the corrected history retains current main as the merge parent so the PR is back to its intended 35-file scope. CI is 118 passing with DCO green, zero unresolved threads, and zero open code-scanning alerts. When convenient, could you please re-review?

@Ricky-G
Ricky Gummadi (Ricky-G) merged commit a8d9bc0 into main Jul 30, 2026
130 checks passed
@Ricky-G
Ricky Gummadi (Ricky-G) deleted the ricky-g/issue-3066-engine-api-fastapi-adapter branch July 30, 2026 00:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-mesh agent-mesh package size/XL Extra large PR (500+ lines) tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Engine API: FastAPI reference adapter + /policies gap-fix (Epic 0, issue 3/32)

5 participants