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
45 changes: 45 additions & 0 deletions DEVLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ crash-stranded `PROCESSING` row. The platform plugin also retains a failed
final draft and reuses its original event id, preventing duplicate final
messages on retry. Focused review coverage passes **33/33** TypeScript tests and
**8/8** Python adapter tests.

## 2026-07-16 — AXI-86 Artifact Studio

Implemented Forge as the artifact control plane for people and agents. The
Expand Down Expand Up @@ -482,6 +483,7 @@ Verification: focused dispatcher and operator-attention coverage passed
passed; the full Vitest suite passed (**1,211 passed; 1 skipped**); a fresh
production build and the responsive Command Center Playwright contract passed
(**1/1** across desktop, tablet, and mobile); and `git diff --check` passed.

## 2026-07-13 — Artifacts system research and implementation brief

Created a documentation-only Artifacts audit in an isolated worktree using
Expand Down Expand Up @@ -13571,6 +13573,49 @@ Mission Control Playwright suite passed both journeys.

---

## 2026-07-16 — Canonical agent connections and delivery ownership

Introduced `AgentConnection` as the durable identity for managed runtimes, MCP
clients, webhooks, and on-demand execution. Runs, run events, work sessions, and
participants now preserve connection provenance and liveness confidence, while
MCP initialization establishes a session identity that is refreshed on every
request and revoked with its API key.

Separated transport-specific liveness semantics: managed runtimes retain
heartbeat/stall recovery, while silent MCP clients become quiet and
unconfirmed without losing delivery ownership or being automatically
redispatched. Work sessions now enforce one active primary connection, support
explicit join and handoff operations, and block conflicting runtime dispatch
with an actionable operator request. PR merge reconciliation also closes
pre-merge execute runs so delivery state cannot remain falsely active.

Expanded Agent Profile, Access, Command Center, Agent Policy, and issue Delivery
surfaces with connection type, confidence, last-seen evidence, participants,
ownership conflicts, and audited reconciliation. Updated the operator and
transport documentation and refreshed the Agent Studio audit captures.

Release review tightened the migration and recovery edges: a connectionless
legacy lease can now be adopted only by a valid connection for the same linked
agent, self-join preserves or repairs the primary participant, and both explicit
delivery heartbeats and generic authenticated MCP signals resolve obsolete
quiet-client recovery asks. The compact runtime tool profile keeps the complete
agent chat loop while moving connector-only negotiation/delivery behind the
catalog, preserving its combined sub-50 provider budget.

The issue Activity surface now classifies unattributed worker, automation, and
connector events instead of rendering a bare `system` actor. Generic issue
updates use payload evidence to summarize delivery actions, changed fields, and
label deltas, falling back to compact “Updated” copy only when no meaningful
detail exists.

Verification: Prisma validation passed; lint and typecheck passed (existing
lint warnings only); focused release-review coverage passed 27/27; the complete
Vitest suite passed 1,386 tests with one intentional live-connector skip; the
fresh production Next.js build passed; and the final production-mode Playwright
run passed all 52 journeys.

---

## 2026-07-15 — Mission Control attention surfaces

Audited Mission Control, the cross-workspace Inbox, Activity, and top-bar
Expand Down
18 changes: 15 additions & 3 deletions docs/agents/profiles-and-bindings.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Agent Profiles & Bindings

An agent in Forge isn't a single row. It's a **three-tier** model:
An agent in Forge isn't a single row. Its durable identity and governance use a
**three-tier** model:

1. A global **profile** — the agent's definition (who it is, what it
can do), owned by a user, independent of any workspace.
Expand All @@ -14,6 +15,12 @@ This is why the same `victor` can work in three workspaces with
different capacity and dispatch rules in each, while staying one
identity everywhere.

Execution adds a fourth, attempt-scoped primitive: **AgentConnection**. A
connection is one concrete managed runtime, MCP client, webhook, or on-demand
endpoint acting through a workspace binding. It is intentionally not another
identity tier: one binding may have several connections, and each run or work
session snapshots the connection that actually performed the work.

## Tier 1 — Profiles (the definition)

A **profile** (`AgentProfile`) is the source of truth for an agent's
Expand Down Expand Up @@ -100,11 +107,15 @@ member can **request** one:
Profiles created directly by an instance admin skip this — they're
pre-approved at creation (`requestedById` stays null).

## MCP clients (the connection credentials)
## MCP clients (credentials and connections)

MCP clients are **not execution runtimes**. A profile has at most one primary
runtime, while each workspace binding may have any number of linked `ApiKey`
credentials for Codex, Claude, Hermes, or other trusted MCP clients.
credentials for Codex, Claude, Hermes, or other trusted MCP clients. The key is
only authentication. An MCP initialize handshake registers an
`AgentConnection` containing the client name/version, negotiated session id,
capabilities, and last-seen state. Rotating a key therefore does not rewrite
the connection recorded on historical runs or deliveries.

Create, inspect, rotate, revoke, and remove those credentials at
**`/w/[slug]/settings/access`**. Mission Control aggregates the linked clients by
Expand All @@ -123,6 +134,7 @@ preselected. The former `/settings/clients` and
See [Runtimes](/agents/runtimes.html).
- **MCP clients** — each binding can hold zero-or-many linked credentials;
these authenticate clients but do not replace the primary execution runtime.
The clients themselves appear as distinct Agent Connections.
- **Auto-dispatch** — `autoDispatchEligible` and the binding's
`capabilities` feed the workspace dispatcher; `autoDispatchMode`
(which agent gets picked) is a different axis from engagement mode
Expand Down
30 changes: 30 additions & 0 deletions docs/agents/providers-and-transports.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,36 @@ There are two independent axes:
runtime) or **Streaming/Completions** (Forge). Orthogonal to tier; see
[Chat & Dispatch Engines](./engines.md).

There are also four deliberately separate identities in the execution record:

- **Agent profile / binding** — who is acting and what it may do in the
workspace.
- **Agent connection** — the concrete managed runtime, MCP client, webhook, or
on-demand endpoint used for this attempt.
- **Agent run** — one execution attempt against an issue.
- **Work session** — the primary branch and pull-request coordination lease.

An API key authenticates a caller; it is not the execution identity. Forge
snapshots the connection on runs and work sessions so key rotation or later
profile relinking cannot rewrite historical attribution.

## Connection-aware liveness

Availability is interpreted from the connection's declared liveness model,
not from its provider name:

| Connection | Positive signals | Silence means |
|---|---|---|
| Managed runtime | Runtime heartbeat, run events, provider state | A confirmed stall is possible after the workspace threshold |
| MCP client | MCP initialize/session, tool calls, explicit lease heartbeat | Quiet / status unconfirmed; never a confirmed stall from silence alone |
| Webhook | Durable delivery plus acknowledgement | Delivery failed or acknowledgement missing |
| On-demand | Successful probe when invoked | Not currently running; global online/offline is not meaningful |

Git commits, pull-request changes, checks, and reviews count as work evidence,
but do not claim that a client process is alive. Operator surfaces show both
the latest lifecycle signal and the latest external work evidence, along with
the confidence of the resulting state.

## Tier 1 — First-class agents (managed runtimes)

The agent is a **full workspace member**: always-on presence, realtime chat,
Expand Down
3 changes: 3 additions & 0 deletions docs/agents/runtimes.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ A Mission Control agent profile selects **zero or one primary execution runtime*
Codex, Claude, Hermes, and custom MCP clients connect with separate linked
credentials in the workspace's **Agent access** page; a binding can have many
of those clients. Adding an MCP client never changes the profile's runtime.
Both are represented as concrete `AgentConnection` endpoints when they
participate in work, so delivery attribution can say “Codex via Codex Desktop
MCP” or “Victor via Hermes runtime” without changing the Agent identity.
:::

::: tip Distinct from `runtimeMode`
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/audits/agent-studio-2026-07-15/after/05-add-mcp-client.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/audits/agent-studio-2026-07-15/after/06-global-runtimes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/audits/agent-studio-2026-07-15/after/09-agent-access.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/audits/agent-studio-2026-07-15/after/11-mission-control.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions docs/engineering/work-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ Branch names include the issue key and owner namespace, for example
Never work directly in a long-lived integration/release branch or in the
production checkout.

The lease is owned by a concrete execution connection, not merely an Agent
Profile. Two MCP clients, or an MCP client and a managed runtime, remain
distinct participants even when they act as the same logical agent. One
connection is primary; additional connections must explicitly join as a
contributor or reviewer, or receive an audited handoff before changing the
branch or advancing delivery state.

## Project branch contract

Branch topology is project configuration, not an Axiom-wide constant. Every
Expand Down Expand Up @@ -56,6 +63,9 @@ integration, scheduled stabilization, or an upstream convention.
mirrors those facts into the delivery lifecycle.
- Resolve file overlap in the PR. Do not move uncommitted patches between
worktrees or share one worktree between tasks.
- If dispatch discovers an existing primary connection, block a second execute
attempt and ask the operator to join, hand off, or cancel. Never infer that
two connections are the same owner from a shared Agent Profile or API key.

## Delivery lifecycle

Expand Down
200 changes: 200 additions & 0 deletions prisma/migrations/20260716170000_agent_connections/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
-- Separate logical agent identity from the concrete endpoint performing work.
-- Legacy provenance is backfilled only where the transport is unambiguous;
-- ambiguous FORGE_AGENT sessions intentionally remain nullable.

CREATE TYPE "AgentConnectionKind" AS ENUM ('MANAGED_RUNTIME', 'MCP_CLIENT', 'WEBHOOK', 'ON_DEMAND');
CREATE TYPE "AgentConnectionLiveness" AS ENUM ('HEARTBEAT', 'LEASE', 'ON_DEMAND', 'PUSH_ACK');
CREATE TYPE "AgentConnectionStatus" AS ENUM ('ACTIVE', 'QUIET', 'DISCONNECTED', 'REVOKED');
CREATE TYPE "LivenessConfidence" AS ENUM ('UNCONFIRMED', 'INFERRED', 'CONFIRMED');
CREATE TYPE "AgentConnectionCapability" AS ENUM ('HEARTBEAT', 'LIFECYCLE_REPORTING', 'CANCELLATION', 'STREAMING', 'TOOL_ACTIVITY', 'PUSH_ACK');
CREATE TYPE "WorkSessionParticipantRole" AS ENUM ('PRIMARY', 'CONTRIBUTOR', 'REVIEWER');

CREATE TABLE "AgentConnection" (
"id" TEXT NOT NULL,
"workspaceId" TEXT NOT NULL,
"agentId" TEXT NOT NULL,
"kind" "AgentConnectionKind" NOT NULL,
"livenessModel" "AgentConnectionLiveness" NOT NULL,
"status" "AgentConnectionStatus" NOT NULL DEFAULT 'QUIET',
"confidence" "LivenessConfidence" NOT NULL DEFAULT 'UNCONFIRMED',
"runtimeId" TEXT,
"apiKeyId" TEXT,
"instanceKey" TEXT,
"displayName" TEXT,
"clientName" TEXT,
"clientVersion" TEXT,
"capabilities" "AgentConnectionCapability"[] NOT NULL DEFAULT ARRAY[]::"AgentConnectionCapability"[],
"metadata" JSONB,
"firstSeenAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"lastSeenAt" TIMESTAMP(3),
"connectedAt" TIMESTAMP(3),
"disconnectedAt" TIMESTAMP(3),
"revokedAt" TIMESTAMP(3),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "AgentConnection_pkey" PRIMARY KEY ("id")
);

ALTER TABLE "AgentRun"
ADD COLUMN "connectionId" TEXT,
ADD COLUMN "lifecycleConfidence" "LivenessConfidence" NOT NULL DEFAULT 'UNCONFIRMED';

ALTER TABLE "AgentRunEvent" ADD COLUMN "connectionId" TEXT;
ALTER TABLE "WorkSession" ADD COLUMN "ownerConnectionId" TEXT;

CREATE TABLE "WorkSessionParticipant" (
"id" TEXT NOT NULL,
"workspaceId" TEXT NOT NULL,
"workSessionId" TEXT NOT NULL,
"connectionId" TEXT NOT NULL,
"agentId" TEXT NOT NULL,
"role" "WorkSessionParticipantRole" NOT NULL,
"joinedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"leftAt" TIMESTAMP(3),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "WorkSessionParticipant_pkey" PRIMARY KEY ("id")
);

-- Managed runtimes are the strongest deterministic legacy mapping.
INSERT INTO "AgentConnection" (
"id", "workspaceId", "agentId", "kind", "livenessModel", "status",
"confidence", "runtimeId", "instanceKey", "displayName", "capabilities",
"firstSeenAt", "lastSeenAt", "connectedAt", "createdAt", "updatedAt"
)
SELECT
'ac_' || md5(a."id" || ':runtime:' || a."runtimeId"),
a."workspaceId", a."id", 'MANAGED_RUNTIME', 'HEARTBEAT',
CASE WHEN a."status" = 'OFFLINE' THEN 'QUIET'::"AgentConnectionStatus" ELSE 'ACTIVE'::"AgentConnectionStatus" END,
'INFERRED', a."runtimeId", 'runtime:' || a."runtimeId", r."name",
ARRAY['HEARTBEAT', 'LIFECYCLE_REPORTING', 'CANCELLATION', 'STREAMING']::"AgentConnectionCapability"[],
COALESCE(a."createdAt", CURRENT_TIMESTAMP),
COALESCE(a."lastHeartbeatAt", r."heartbeatAt"), r."connectedAt",
COALESCE(a."createdAt", CURRENT_TIMESTAMP), CURRENT_TIMESTAMP
FROM "Agent" a
JOIN "Runtime" r ON r."id" = a."runtimeId"
WHERE a."runtimeId" IS NOT NULL
ON CONFLICT DO NOTHING;

-- CODEX_DESKTOP is an explicit historical transport signal. One conservative
-- legacy client is created per agent; future MCP initialize calls register
-- their real session/client instances separately.
INSERT INTO "AgentConnection" (
"id", "workspaceId", "agentId", "kind", "livenessModel", "status",
"confidence", "instanceKey", "displayName", "clientName", "capabilities",
"firstSeenAt", "lastSeenAt", "createdAt", "updatedAt"
)
SELECT
'ac_' || md5(a."id" || ':legacy:codex-desktop'),
a."workspaceId", a."id", 'MCP_CLIENT', 'LEASE', 'QUIET', 'INFERRED',
'legacy:codex-desktop:' || a."id", 'Codex Desktop (legacy)', 'Codex Desktop',
ARRAY['TOOL_ACTIVITY']::"AgentConnectionCapability"[],
MIN(ws."createdAt"), MAX(ws."lastHeartbeatAt"), MIN(ws."createdAt"), CURRENT_TIMESTAMP
FROM "WorkSession" ws
JOIN "Agent" a ON a."id" = ws."ownerAgentId"
WHERE ws."source" = 'CODEX_DESKTOP'
GROUP BY a."id", a."workspaceId"
ON CONFLICT DO NOTHING;

-- A configured direct webhook is also an unambiguous endpoint. Keep it
-- distinct even when the same agent additionally has a managed runtime.
INSERT INTO "AgentConnection" (
"id", "workspaceId", "agentId", "kind", "livenessModel", "status",
"confidence", "instanceKey", "displayName", "capabilities",
"firstSeenAt", "lastSeenAt", "createdAt", "updatedAt"
)
SELECT
'ac_' || md5(a."id" || ':webhook'), a."workspaceId", a."id",
'WEBHOOK', 'PUSH_ACK', 'QUIET', 'UNCONFIRMED',
'legacy:webhook:' || a."id", a."name" || ' webhook',
ARRAY['PUSH_ACK']::"AgentConnectionCapability"[],
a."createdAt", a."lastHeartbeatAt", a."createdAt", CURRENT_TIMESTAMP
FROM "Agent" a
WHERE a."webhookUrl" IS NOT NULL
ON CONFLICT DO NOTHING;

-- Backfill work-session provenance only for explicit Codex Desktop sessions or
-- an agent's managed runtime. FORGE_AGENT without a runtime remains unknown:
-- linked API keys historically represented both identity and transport.
UPDATE "WorkSession" ws
SET "ownerConnectionId" = ac."id"
FROM "AgentConnection" ac
WHERE ws."ownerAgentId" = ac."agentId"
AND ws."workspaceId" = ac."workspaceId"
AND (
(ws."source" = 'CODEX_DESKTOP' AND ac."kind" = 'MCP_CLIENT')
OR
(ws."source" = 'FORGE_AGENT' AND ac."kind" = 'MANAGED_RUNTIME')
);

-- A run can be mapped when its agent has one managed runtime. Other historical
-- runs stay unconfirmed rather than acquiring fabricated MCP provenance.
UPDATE "AgentRun" ar
SET "connectionId" = ac."id", "lifecycleConfidence" = 'INFERRED'
FROM "AgentConnection" ac
WHERE ar."agentId" = ac."agentId"
AND ar."workspaceId" = ac."workspaceId"
AND ac."kind" = 'MANAGED_RUNTIME';

UPDATE "AgentRunEvent" are
SET "connectionId" = ar."connectionId"
FROM "AgentRun" ar
WHERE are."runId" = ar."id" AND ar."connectionId" IS NOT NULL;

INSERT INTO "WorkSessionParticipant" (
"id", "workspaceId", "workSessionId", "connectionId", "agentId", "role",
"joinedAt", "createdAt", "updatedAt"
)
SELECT
'wsp_' || md5(ws."id" || ':' || ws."ownerConnectionId"),
ws."workspaceId", ws."id", ws."ownerConnectionId", ws."ownerAgentId",
'PRIMARY', ws."createdAt", ws."createdAt", CURRENT_TIMESTAMP
FROM "WorkSession" ws
WHERE ws."ownerConnectionId" IS NOT NULL AND ws."ownerAgentId" IS NOT NULL
ON CONFLICT DO NOTHING;

CREATE UNIQUE INDEX "AgentConnection_workspaceId_agentId_kind_instanceKey_key"
ON "AgentConnection"("workspaceId", "agentId", "kind", "instanceKey");
CREATE INDEX "AgentConnection_workspaceId_status_lastSeenAt_idx"
ON "AgentConnection"("workspaceId", "status", "lastSeenAt");
CREATE INDEX "AgentConnection_agentId_kind_status_idx"
ON "AgentConnection"("agentId", "kind", "status");
CREATE INDEX "AgentConnection_runtimeId_idx" ON "AgentConnection"("runtimeId");
CREATE INDEX "AgentConnection_apiKeyId_idx" ON "AgentConnection"("apiKeyId");
CREATE INDEX "AgentRun_connectionId_status_idx" ON "AgentRun"("connectionId", "status");
CREATE INDEX "AgentRunEvent_connectionId_createdAt_idx" ON "AgentRunEvent"("connectionId", "createdAt");
CREATE INDEX "WorkSession_ownerConnectionId_status_idx" ON "WorkSession"("ownerConnectionId", "status");
CREATE UNIQUE INDEX "WorkSessionParticipant_workSessionId_connectionId_key"
ON "WorkSessionParticipant"("workSessionId", "connectionId");
CREATE INDEX "WorkSessionParticipant_workspaceId_role_leftAt_idx"
ON "WorkSessionParticipant"("workspaceId", "role", "leftAt");
CREATE INDEX "WorkSessionParticipant_agentId_leftAt_idx"
ON "WorkSessionParticipant"("agentId", "leftAt");
CREATE INDEX "WorkSessionParticipant_connectionId_leftAt_idx"
ON "WorkSessionParticipant"("connectionId", "leftAt");
CREATE UNIQUE INDEX "WorkSessionParticipant_one_active_primary"
ON "WorkSessionParticipant"("workSessionId")
WHERE "role" = 'PRIMARY' AND "leftAt" IS NULL;

ALTER TABLE "AgentConnection" ADD CONSTRAINT "AgentConnection_workspaceId_fkey"
FOREIGN KEY ("workspaceId") REFERENCES "Workspace"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "AgentConnection" ADD CONSTRAINT "AgentConnection_agentId_fkey"
FOREIGN KEY ("agentId") REFERENCES "Agent"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "AgentConnection" ADD CONSTRAINT "AgentConnection_runtimeId_fkey"
FOREIGN KEY ("runtimeId") REFERENCES "Runtime"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "AgentConnection" ADD CONSTRAINT "AgentConnection_apiKeyId_fkey"
FOREIGN KEY ("apiKeyId") REFERENCES "ApiKey"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "AgentRun" ADD CONSTRAINT "AgentRun_connectionId_fkey"
FOREIGN KEY ("connectionId") REFERENCES "AgentConnection"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "AgentRunEvent" ADD CONSTRAINT "AgentRunEvent_connectionId_fkey"
FOREIGN KEY ("connectionId") REFERENCES "AgentConnection"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "WorkSession" ADD CONSTRAINT "WorkSession_ownerConnectionId_fkey"
FOREIGN KEY ("ownerConnectionId") REFERENCES "AgentConnection"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "WorkSessionParticipant" ADD CONSTRAINT "WorkSessionParticipant_workspaceId_fkey"
FOREIGN KEY ("workspaceId") REFERENCES "Workspace"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "WorkSessionParticipant" ADD CONSTRAINT "WorkSessionParticipant_workSessionId_fkey"
FOREIGN KEY ("workSessionId") REFERENCES "WorkSession"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "WorkSessionParticipant" ADD CONSTRAINT "WorkSessionParticipant_connectionId_fkey"
FOREIGN KEY ("connectionId") REFERENCES "AgentConnection"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "WorkSessionParticipant" ADD CONSTRAINT "WorkSessionParticipant_agentId_fkey"
FOREIGN KEY ("agentId") REFERENCES "Agent"("id") ON DELETE CASCADE ON UPDATE CASCADE;
Loading
Loading