Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Dockerfile.acp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM golang:1.26.5-alpine AS build
ARG TARGETOS
ARG TARGETARCH
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \
go build -buildvcs=false -trimpath -ldflags='-s -w' -o /out/agent-runtime-foundry .
ARG FOUNDRY_CONFIG=examples/foundry-acp.json
COPY ${FOUNDRY_CONFIG} /out/rootfs/agent/foundry.json
RUN chmod 0555 /out/rootfs/agent && chmod 0444 /out/rootfs/agent/foundry.json

FROM gcr.io/distroless/static:nonroot@sha256:1c2c046bc09ed40fad370b599a0b1ae7987f55b01e247cf27a7c27cd97e5bbc7
COPY --from=build --chown=0:0 --chmod=0555 /out/agent-runtime-foundry /agent-runtime-foundry
COPY --from=build --chown=0:0 /out/rootfs/ /
USER 65532:65532
ENTRYPOINT ["/agent-runtime-foundry"]
CMD ["--protocol", "acp", "--config", "/agent/foundry.json"]
39 changes: 39 additions & 0 deletions Dockerfile.hosted
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# syntax=docker/dockerfile:1
# Build the configured ACP image, compose it with Orka's supervisor, then use
# that immutable composition here. Only the public hosted configuration enters
# this image. The gateway retains Azure identity and all bootstrap secrets.
ARG ORKA_RUNTIME_IMAGE
FROM ${ORKA_RUNTIME_IMAGE} AS runtime

# This filesystem was exercised on Foundry Hosted Agents with the actual Orka
# exec helper. A distroless filesystem did not start in that environment.
FROM docker.io/library/python:3.12-slim@sha256:2fe5997d249a808b8eeea52c58a1dbffbba28754dc11699ef5c029f2d818ce79
ARG ORKA_RUNTIME_IMAGE
ARG FOUNDRY_ADAPTER_DIGEST
ARG HOSTED_CONFIG
RUN set -eu; \
case "$ORKA_RUNTIME_IMAGE" in *@sha256:*) ;; *) exit 1 ;; esac; \
digest="${ORKA_RUNTIME_IMAGE##*@sha256:}"; \
test "${#digest}" -eq 64; \
case "$digest" in *[!0-9a-f]*) exit 1 ;; esac; \
case "$FOUNDRY_ADAPTER_DIGEST" in sha256:*) ;; *) exit 1 ;; esac; \
digest="${FOUNDRY_ADAPTER_DIGEST#sha256:}"; \
test "${#digest}" -eq 64; \
case "$digest" in *[!0-9a-f]*) exit 1 ;; esac; \
mkdir -p /agent; chmod 0555 /agent
COPY --from=runtime --chown=0:0 --chmod=0555 /agent-runtime-foundry /agent-runtime-foundry
COPY --from=runtime --chown=0:0 --chmod=0555 /usr/local/bin/orka-acp-runtime /usr/local/bin/orka-acp-runtime
COPY --from=runtime --chown=0:0 --chmod=0555 /usr/local/bin/orka-acp-exec-helper /usr/local/bin/orka-acp-exec-helper
COPY --from=runtime --chown=0:0 --chmod=0444 /agent/foundry.json /agent/foundry.json
COPY --chown=0:0 --chmod=0444 ${HOSTED_CONFIG} /agent/hosted.json
ENV PORT=8088 ORKA_ACP_FOUNDRY_ADAPTER_DIGEST=${FOUNDRY_ADAPTER_DIGEST}
LABEL org.opencontainers.image.title="Orka-governed Foundry Hosted Agent" \
org.opencontainers.image.source="https://github.com/orka-agents/agent-runtime-foundry" \
io.orka.harness.protocol="orka.harness.v2"
WORKDIR /
# Only the supervisor is privileged. It assigns distinct UIDs/GIDs to ACP children.
USER 0:0
EXPOSE 8088
STOPSIGNAL SIGTERM
ENTRYPOINT ["/agent-runtime-foundry"]
CMD ["--protocol", "hosted", "--config", "/agent/hosted.json"]
40 changes: 26 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
# Microsoft Foundry Hosted Agents adapter for Orka

This repository presents a deployed **Microsoft Foundry Hosted Agent** that
implements the Responses protocol as an
This repository connects a deployed **Microsoft Foundry Hosted Agent** to Orka.
For harness v2, use the [ACP child and durable Foundry broker](docs/harness-v2.md)
with Orka's existing supervisor. The default HTTP entry point exposes the
Responses agent as an
[`orka.harness.v1`](https://github.com/orka-agents/orka/blob/main/website/docs/development/agent-runtime-adapter-contract.md)
`AgentRuntime` endpoint.

To run the supervisor and ACP child inside Foundry itself, use the
[Hosted Agent v2 package and Kubernetes gateway](docs/foundry-hosted-v2.md).

The adapter calls the Hosted Agent's dedicated Responses endpoint:

```text
Expand All @@ -21,7 +26,7 @@ are never sent to Foundry.

## Status

The adapter is experimental. Run a single replica. Runtime-session and active
The adapter is experimental. Run a single replica. In harness v1, runtime-session and active
turn state are currently process-local, so a pod replacement cannot resume a
retained session or deduplicate an active turn. Orka facade samples use an external endpoint and do
not install or manage this adapter.
Expand All @@ -31,15 +36,20 @@ not install or manage this adapter.
Deploy a Hosted Agent that exposes the Responses protocol. The agent container
must implement the Foundry Hosted Agent Responses contract (`POST /responses`
and `GET /readiness`). The adapter invokes the deployed agent through the
project endpoint; it is not the Hosted Agent container itself.

The Hosted Agent must honor function tools supplied on each Responses request
for Orka brokered-tool mode. Brokered profiles are disabled by default; enable
only the classes the deployed agent has passed in conformance. If the agent
ignores request-provided function tools, keep observed mode or update the agent
implementation. Do not move Orka
production tool credentials into Foundry Toolbox or MCP merely to make a probe
pass; that changes the governance boundary.
project endpoint. The default adapter runs outside Foundry; the optional
v2 hosted package runs its supervisor inside a separate Hosted Agent.

For Orka brokered-tool mode, use one of two schema delivery modes. The default
`request` mode requires the Hosted Agent endpoint to accept function tools on
each Responses request. `provider-static` mode is available for Hosted Agent
endpoints that reject request-level tools; in that mode the Hosted Agent must
preconfigure the function schemas. The adapter still rejects any function call
that was not supplied in the current Orka turn, and Orka still owns argument
validation, policy, approvals, credentials, execution, and audit. Brokered
profiles are disabled by default; enable only the classes and schema mode the
deployed agent has passed in conformance. Do not move Orka production tool
credentials into Foundry Toolbox or MCP merely to make a probe pass; that
changes the governance boundary.

## Configuration

Expand All @@ -56,7 +66,8 @@ pass; that changes the governance boundary.
| `ORKA_FOUNDRY_TURN_TIMEOUT` | Absolute adapter maximum for one Orka turn, default `20s`. |
| `ORKA_FOUNDRY_ISOLATION_MODE` | `entra` (default) or `header`. In `header` mode, the adapter sends an opaque hash of Orka's runtime session ID as `x-ms-user-isolation-key`. |
| `ORKA_FOUNDRY_FEATURES` | Preview feature header value, default `HostedAgents=V1Preview`. Set an empty value only when the deployed API no longer requires the header. |
| `ORKA_FOUNDRY_BROKERED_TOOL_CLASSES` | Optional comma-separated classes to advertise and accept: `read`, `write`, or `read,write`. Empty by default (observed-only). Enable only after the Hosted Agent passes the matching conformance probes with request-provided function tools. |
| `ORKA_FOUNDRY_BROKERED_TOOL_CLASSES` | Optional comma-separated classes to advertise and accept: `read`, `write`, or `read,write`. Empty by default (observed-only). Enable only after the Hosted Agent passes the matching conformance probes in the configured schema mode. |
| `ORKA_FOUNDRY_TOOL_SCHEMA_MODE` | Brokered schema delivery: `request` (default) sends Orka's safe function schemas on each Responses request; `provider-static` omits request-level tools and requires matching schemas to be preconfigured in the Hosted Agent. |

The adapter authenticates with Azure SDK `DefaultAzureCredential` and requests
the `https://ai.azure.com/.default` scope. In Kubernetes, use Azure Workload
Expand Down Expand Up @@ -108,7 +119,8 @@ spec:
`store: true`.
- `response.created` becomes `TurnStarted`.
- `response.output_text.delta` becomes `RuntimeOutput`.
- When explicitly enabled, request-provided safe Orka tool schemas become Responses function tools.
- When explicitly enabled in `request` mode, request-provided safe Orka tool schemas become Responses function tools.
- In `provider-static` mode, the provider uses its preconfigured schemas while the adapter enforces every returned function name against the current turn's Orka-supplied allowlist.
- `function_call` output items become `ToolCallRequested` frames.
- `/v1/turns/{turnID}/continue` sends `function_call_output` items with the same
`call_id` and chains them with `previous_response_id`.
Expand Down
Loading