Skip to content

feat(runtime): add Orka harness v2 ACP mode - #22

Merged
sozercan merged 23 commits into
mainfrom
feat/orka-harness-v2
Sep 11, 2026
Merged

sozercan merged 23 commits into
mainfrom
feat/orka-harness-v2

Conversation

@sozercan

@sozercan sozercan commented Sep 3, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • add an ACP stdio mode for agentkit-serve so AgentKit runtimes can run behind Orka harness v2
  • map session lifecycle, prompt streaming, cancellation, and Orka HTTP MCP projection across the supported runtime adapters
  • document the new mode and add common protocol plus adapter guardrail coverage

Companion Orka PR: orka-agents/orka#487

Validation

  • common ACP and CLI tests: 28 passed
  • Microsoft Agent Framework guardrails: 29 passed
  • focused LangGraph and Pydantic AI offline tests passed
  • go test ./...
  • make lint
  • final autoreview clean

The unfiltered common pytest collection still hits the existing Foundry dependency import error for get_input_expanded; the focused common ACP and CLI suite passes.

Signed-off-by: Sertac Ozercan <sozercan@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

ACP update-delivery failures can leave framework state inconsistent with uncommitted protocol history.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 1 Medium severity

New issues introduced by this change (1)
Severity Finding
Medium severity runtimes/​common/​agentkit_serve_common/​acp.py — If emitting the update fails (for example, serve_acp_stdio.send rejects a response over 8 MiB),…
What changed in this PR

Adds ACP stdio support for AgentKit runtimes behind Orka harness v2.

Changes:

  • Implements ACP sessions, prompts, cancellation, MCP projection, and strict runtime binding.
  • Adds adapter capabilities and MAF session rollback.
  • Adds protocol tests and documentation.

Review finding: ACP output failures can leave MAF session state inconsistent with ACP history.

File Description
README.md Documents ACP mode.
docs/​orka.md Describes harness v2 integration.
docs/​runtime-adapters.md Documents ACP architecture.
runtimes/​common/​README.md Adds common ACP guidance.
runtimes/​common/​agentkit_serve_common/​acp.py Implements ACP stdio server.
runtimes/​common/​agentkit_serve_common/​cli.py Adds ACP CLI routing.
runtimes/​common/​agentkit_serve_common/​runtime.py Enables ACP offline echo.
runtimes/​common/​tests/​test_acp_protocol.py Covers ACP behavior and guardrails.
runtimes/​common/​tests/​test_cli_protocol.py Covers ACP CLI startup.
runtimes/​langgraph/​agentkit_serve/​agent_factory.py Advertises HTTP MCP support.
runtimes/​langgraph/​tests/​test_guardrails.py Tests ACP capability.
runtimes/​microsoft-agent-framework/​agentkit_serve/​agent_factory.py Adds session rollback and ACP capability.
runtimes/​microsoft-agent-framework/​tests/​test_guardrails.py Updates session recovery coverage.
runtimes/​pydantic-ai/​agentkit_serve/​agent_factory.py Detects HTTP MCP capability.
runtimes/​pydantic-ai/​tests/​test_unsupported_features.py Tests ACP capability.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread runtimes/common/agentkit_serve_common/acp.py Outdated
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Copilot AI review requested due to automatic review settings September 3, 2026 21:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Oversized input framing can execute a trailing fragment as another request, and valid null request IDs are rejected.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 1 High severity

New issues introduced by this change (1)
Severity Finding
High severity runtimes/​common/​agentkit_serve_common/​acp.py — readline(limit) returns a partial fragment when one input line exceeds the limit. After rejecting…
Issues resolved since last review (1)
Severity Finding
Medium severity runtimes/​common/​agentkit_serve_common/​acp.py — If emitting the update fails (for example, serve_acp_stdio.send rejects a response over 8 MiB),… View resolved comment
Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

runtimes/common/agentkit_serve_common/acp.py:88

  • ACP v1 permits a null JSON-RPC request ID (although it discourages clients from using one). This rejects such a valid request with -32600 instead of dispatching it, so allow None while continuing to reject booleans and other types.

Comment thread runtimes/common/agentkit_serve_common/acp.py Outdated
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Copilot AI review requested due to automatic review settings September 3, 2026 21:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

ACP output frames can exceed Orka’s supervisor limits and terminate otherwise successful sessions.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 1 High severity

New issues introduced by this change (1)
Severity Finding
High severity runtimes/​common/​agentkit_serve_common/​acp.py — The entire model response is emitted as one JSON-RPC line. Orka's supervisor configures its ACP…
Issues resolved since last review (1)
Severity Finding
High severity runtimes/​common/​agentkit_serve_common/​acp.py — readline(limit) returns a partial fragment when one input line exceeds the limit. After rejecting… View resolved comment

Comment thread runtimes/common/agentkit_serve_common/acp.py Outdated
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Copilot AI review requested due to automatic review settings September 3, 2026 22:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Invalid ACP request IDs can be echoed into malformed JSON-RPC error responses.

Review tier: Balanced
Findings: None

Issues resolved since last review (1)
Severity Finding
High severity runtimes/​common/​agentkit_serve_common/​acp.py — The entire model response is emitted as one JSON-RPC line. Orka's supervisor configures its ACP… View resolved comment
Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

runtimes/common/agentkit_serve_common/acp.py:268

  • When the envelope is invalid, this can echo an object, array, boolean, or float from id into the error response. ACP request IDs are only strings or integers, and JSON-RPC requires id: null when a valid request ID cannot be established; normalize invalid values before sending this early error.

This issue also appears in the following locations of the same file:

  • line 273
  • line 282

runtimes/common/agentkit_serve_common/acp.py:273

  • This early method-validation error also bypasses _request_key and echoes an invalid raw id, producing a response outside the ACP/JSON-RPC contract. Use null unless the ID is a non-boolean string or integer.
            await self._send_error(message.get("id"), _INVALID_REQUEST, "JSON-RPC method is required")

runtimes/common/agentkit_serve_common/acp.py:282

  • _request_key rejects invalid ACP IDs, but the error response then echoes that same invalid value. This makes malformed input produce a malformed JSON-RPC response; use id: null when ID validation fails.
            await self._send_protocol_error(response_id, exc)

Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Copilot AI review requested due to automatic review settings September 3, 2026 23:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

ACP initialization rejects unsupported versions instead of performing the protocol’s required version negotiation.

Review tier: Balanced
Findings: None

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

runtimes/common/agentkit_serve_common/acp.py:384

  • ACP v1 requires an agent to return its latest supported protocol version when the requested version is unsupported. Rejecting every value other than 1 with -32602 prevents the required version negotiation for newer clients. Validate that the field is an integer, then let the response advertise ACP_PROTOCOL_VERSION.

Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Copilot AI review requested due to automatic review settings September 4, 2026 03:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Digest validation hashes a second read of a replaceable config, so the parsed runtime spec may differ from the approved content.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 1 High severity

New issues introduced by this change (1)
Severity Finding
High severity runtimes/​common/​agentkit_serve_common/​acp.py — The digest is computed from a second file read after cli._load_spec_or_exit() has already parsed…

Comment thread runtimes/common/agentkit_serve_common/acp.py Outdated
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Copilot AI review requested due to automatic review settings September 4, 2026 03:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The critical MAF rollback path lacks direct adapter-level regression coverage.

Review tier: Balanced
Findings: None

Issues resolved since last review (1)
Severity Finding
High severity runtimes/​common/​agentkit_serve_common/​acp.py — The digest is computed from a second file read after cli._load_spec_or_exit() has already parsed… View resolved comment
Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

runtimes/microsoft-agent-framework/agentkit_serve/agent_factory.py:410

  • discard_session is the rollback path when cancellation or output delivery fails after MAF has already completed a turn, but the MAF guardrails only test resetting when run_agent itself raises. The common ACP tests use a recording fake, so a regression or no-op here would still pass. Add an adapter-level test that completes a run, calls discard_session, then retries the same session ID and verifies that a fresh AgentSession is used with explicit history enabled.

Signed-off-by: Sertac Ozercan <sozercan@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The new security-sensitive protocol, cancellation, and concurrent stdio lifecycle require final human review.

Review tier: Balanced
Findings: None

Emit correlated, redacted tool lifecycle events across the LangGraph,
Microsoft Agent Framework, and Pydantic AI adapters. Settle cancellation,
normalize MAF provider messages, and propagate fatal MCP errors without
replaying tool calls while preserving recoverable admitted errors.

Validation: common and framework suites, Go tests, lint, amd64 image
checks, and live Orka harness v2 conformance and lifecycle checks.

Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Copilot AI review requested due to automatic review settings September 5, 2026 15:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The new security-sensitive protocol and cross-framework lifecycle behavior require final human review against the inaccessible companion Orka contract.

Review tier: Balanced
Findings: None

Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Copilot AI review requested due to automatic review settings September 5, 2026 21:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

LangGraph can expose MCP diagnostics to the model, and ACP error serialization can strand oversized requests.

Review tier: Balanced
Findings: None

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

runtimes/common/agentkit_serve_common/acp.py:889

  • Accepted requests can contain nearly 8 MiB of untrusted text, and several errors interpolate that text (for example the unknown method at line 501 and duplicate header name at line 685). JSON quoting can make the resulting error exceed _MAX_MESSAGE_BYTES; send() then raises, _request_done() only retrieves that task exception, and the client waits without any response. Bound or sanitize error fields at this shared boundary (or terminate the server when a response cannot be written) so malformed-but-accepted frames cannot strand a request.
    runtimes/langgraph/agentkit_serve/agent_factory.py:213
  • This advertises ACP HTTP MCP support, but _load_tools() still uses load_mcp_tools() with its default handle_tool_errors=True. In the allowed langchain-mcp-adapters 0.3.2 release, an admitted CallToolResult(isError=True) becomes a ToolMessage that preserves the MCP error content verbatim, so broker diagnostics are sent into the model context; the new Pydantic AI and MAF paths replace those diagnostics with a generic recovery message. Please add the same redacting boundary here (while preserving model recovery), or do not advertise this capability until that boundary exists.

@sozercan

sozercan commented Sep 7, 2026

Copy link
Copy Markdown
Owner Author

Both current-head Live Vekil/Copilot failures stop at authentication, before the AgentKit live agent is built or invoked. The pull-request job and push job each record Vekil exiting with authentication failed: invalid access token, followed by the /readyz timeout.

At c9a18070363b9eded0be8ca826d8fc5365afc828, the workflow, live E2E script and MAF live-agent fixture are byte-identical to main 8822545874f0e58bc6e84e092f60810d14e0c69d. The other 12 checks passed. These logs do not demonstrate an AgentKit behavior defect.

Live verification is blocked until the configured COPILOT_GITHUB_TOKEN authentication is repaired and these checks are rerun. The failure remains visible; skipping authentication failures would not prove provider integration.

Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Copilot AI review requested due to automatic review settings September 10, 2026 22:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The mutable Vekil image can receive repository or cached credentials and must be pinned to an immutable digest.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 2 High severity

New issues introduced by this change (2)
Severity Finding
High severity .github/​workflows/​ci.yml — Pin the credential-bearing Vekil image by digest
High severity scripts/​live-copilot-agent-e2e.sh — Keep the local Vekil default immutable

Comment thread .github/workflows/ci.yml Outdated
Comment thread scripts/live-copilot-agent-e2e.sh Outdated
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Copilot AI review requested due to automatic review settings September 10, 2026 22:29

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The large cross-runtime protocol, cancellation, and security change requires final human validation against the inaccessible companion Orka implementation.

Review tier: Balanced
Findings: None

Issues resolved since last review (2)
Severity Finding
High severity scripts/​live-copilot-agent-e2e.sh — Keep the local Vekil default immutable View resolved comment
High severity .github/​workflows/​ci.yml — Pin the credential-bearing Vekil image by digest View resolved comment

Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Copilot AI review requested due to automatic review settings September 10, 2026 23:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The concurrency-sensitive protocol and cross-framework changes require final human review against the inaccessible companion Orka contract.

Review tier: Balanced
Findings: None

Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Copilot AI review requested due to automatic review settings September 11, 2026 06:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

ACP parsing and repeated-cancellation cleanup still contain correctness gaps.

Review tier: Balanced
Findings: None

Previously missed findings (2)

In code that hasn't changed since last review

runtimes/common/agentkit_serve_common/acp.py:401

  • json.loads can raise a plain ValueError for an integer longer than Python's conversion limit and RecursionError for deeply nested input. Both fit under the 8 MiB frame limit, so either currently escapes the protocol handler and terminates the ACP child instead of returning a parse error. Catch these decoder failures alongside malformed JSON.
    runtimes/common/agentkit_serve_common/acp.py:455
  • EOF/close commonly follows a cancellation notification. If that prompt is still cleaning up, this unconditional second Task.cancel() can interrupt the adapter's join/teardown path before child tool or provider tasks have stopped. Preserve the first cancellation's cleanup by only issuing cancellation for states not already marked cancelled.

This issue also appears on line 845 of the same file.

@sozercan
sozercan merged commit 9a6de8f into main Sep 11, 2026
15 checks passed
@sozercan
sozercan deleted the feat/orka-harness-v2 branch September 11, 2026 06:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants