OpenJCockpit

Agent runtime

embabel-agent-runtime is the execution plane of OpenJCockpit: the only process that runs agents and calls LLMs. embabel-agent-service is the management plane: it decides which agents a workflow runs, in what order, under which gates and policies, and records the outcome. The two are separate Spring Boot applications, Maven modules and Docker images that communicate only over the HTTP contract described here.

Responsibilities

  embabel-agent-service (management) embabel-agent-runtime (execution)
Workflows definitions, groups, import/export, orchestration (sequential agent chain), approval gates, workflow orbs, run state and history —
Agents catalogue (/agents folder + A2A providers), workflow agent references, tenant bindings (PostgreSQL) resolving and running configuration-driven agents (Embabel ConfiguredDefinitionAgent)
Definitions /agents catalogue folder served agents and skills (agent-definitions/, shipped in the image), last-known-good cache
A2A outbound: provider clients used by workflows and the catalogue inbound: /a2a/{agentId} (JSON-RPC message/send) and Agent Cards
LLM — (no LLM credentials) coding LLM route (LiteLLM / direct Ollama), OpenAI, agent model aliases, definition drafts
Tools — tool registry, bind-time allowlisting, agent git tools (git MCP via LiteLLM)
Policy OPA client, mcp.tool.invoke and all other decisions, decision log export asks the agent service for every tool call
Git workspace tickets (ai-control), run binding, checkpoint commits git tools inside the run’s workspace
Persistence embabel database and its Flyway migrations none (in-memory execution registry only)

The contract

All types live in services/service-common, package nl.metafactory.common.agentruntime (AgentRuntimeApi lists every path).

Agent service → runtime (caller identity openjcockpit-agent-service)

Endpoint Purpose
POST /internal/v1/agent-executions Run one agent synchronously. Body AgentExecutionRequest: executionId, tenantId, agentId, principal, workflowRunId, traceparent, message, and for catalogue (local:) agents a definition snapshot (lookup status + raw Markdown). Answer AgentExecutionResult (text, agent version, content hash, trace id).
GET /internal/v1/agent-executions/{executionId} Lifecycle of an accepted execution (RUNNING, COMPLETED, FAILED); never the output.
POST /internal/v1/definition-drafts/{agent\|subagent\|skill} LLM draft for the workflow designer; the agent service sanitises it.

Failures are AgentExecutionFailure bodies with a stable reason: INVALID_REQUEST (400), FORBIDDEN (403), UNKNOWN_EXECUTION (404), DUPLICATE_EXECUTION (409), a resolution failure such as TENANT_FORBIDDEN, NOT_FOUND, INVALID, TOOL_DENIED, GUARDRAIL_MISSING or GUARDRAIL_VIOLATION (422), UNAVAILABLE (503), EXECUTION_FAILED (500). Messages never contain prompts, outputs or secrets.

Runtime → agent service (caller identity openjcockpit-agent-runtime)

Endpoint Purpose
GET /internal/agent-runtime/v1/tenants/{tenantId}/agent-bindings/{agentId} The tenant’s binding (enabled, pins, tool allowlist, required guardrails); 404 when none.
GET /internal/agent-runtime/v1/workflow-runs/{runId} Scope of an active run (workflow id, git workspace); 404 when unknown or finished.
POST /internal/agent-runtime/v1/tool-invocation-decisions OPA decision (mcp.tool.invoke) for one tool call, written to the agent service’s decision log.

How agents reach the runtime

Security model

Long-running executions, timeouts and duplicates

An execution is one synchronous request, exactly like the in-process call it replaces: the workflow engine’s pipeline thread waits (default openjcockpit.agent-runtime.execution-timeout: 60m). The client never retries. Each invocation gets a unique executionId (<runId>:<uuid>); the runtime accepts an id once and refuses a second request with 409 DUPLICATE_EXECUTION, so a proxy retry or a resent request can never run an agent twice. When the agent service gets no answer it asks GET /internal/v1/agent-executions/{id} and reports whether the agent is still running — it does not resend.

Cancellation keeps its existing semantics: stopping a workflow run takes effect between agents; an agent that is already running finishes (there was no mid-agent cancellation before either). Streaming is not supported (A2A message/stream is rejected explicitly, as before).

Operations