diff --git a/apps/webapp/app/presenters/v3/SpanPresenter.server.ts b/apps/webapp/app/presenters/v3/SpanPresenter.server.ts
index b2fd1d1c1..0c16a5cc9 100644
--- a/apps/webapp/app/presenters/v3/SpanPresenter.server.ts
+++ b/apps/webapp/app/presenters/v3/SpanPresenter.server.ts
@@ -218,6 +218,7 @@ export class SpanPresenter extends BasePresenter {
friendlyId: true,
},
},
+ replayedFromTaskRunFriendlyId: true,
},
where: span.originalRun
? {
@@ -331,6 +332,7 @@ export class SpanPresenter extends BasePresenter {
runtime: run.lockedToVersion?.runtime,
runtimeVersion: run.lockedToVersion?.runtimeVersion,
isTest: run.isTest,
+ replayedFromTaskRunFriendlyId: run.replayedFromTaskRunFriendlyId,
environmentId: run.runtimeEnvironment.id,
idempotencyKey: run.idempotencyKey,
idempotencyKeyExpiresAt: run.idempotencyKeyExpiresAt,
diff --git a/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx b/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
index 22dbacde4..2c85b0aa5 100644
--- a/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
+++ b/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
@@ -63,6 +63,7 @@ import {
v3DeploymentVersionPath,
v3RunDownloadLogsPath,
v3RunPath,
+ v3RunRedirectPath,
v3RunSpanPath,
v3RunsPath,
v3SchedulePath,
@@ -592,6 +593,20 @@ function RunBody({
{run.isTest ? : "–"}
+ {run.replayedFromTaskRunFriendlyId && (
+
+ Replayed from
+
+
+ {run.replayedFromTaskRunFriendlyId}
+
+
+
+ )}
{environment && (
Environment
diff --git a/apps/webapp/app/runEngine/services/triggerTask.server.ts b/apps/webapp/app/runEngine/services/triggerTask.server.ts
index 939e3a682..caa9aafc4 100644
--- a/apps/webapp/app/runEngine/services/triggerTask.server.ts
+++ b/apps/webapp/app/runEngine/services/triggerTask.server.ts
@@ -264,6 +264,7 @@ export class RunEngineTriggerTaskService {
spanId: event.spanId,
parentSpanId:
options.parentAsLinkType === "replay" ? undefined : event.traceparent?.spanId,
+ replayedFromTaskRunFriendlyId: options.replayedFromTaskRunFriendlyId,
lockedToVersionId: lockedToBackgroundWorker?.id,
taskVersion: lockedToBackgroundWorker?.version,
sdkVersion: lockedToBackgroundWorker?.sdkVersion,
diff --git a/apps/webapp/app/v3/services/replayTaskRun.server.ts b/apps/webapp/app/v3/services/replayTaskRun.server.ts
index 51501605c..42b3aac80 100644
--- a/apps/webapp/app/v3/services/replayTaskRun.server.ts
+++ b/apps/webapp/app/v3/services/replayTaskRun.server.ts
@@ -87,6 +87,7 @@ export class ReplayTaskRunService extends BaseService {
{
spanParentAsLink: true,
parentAsLinkType: "replay",
+ replayedFromTaskRunFriendlyId: existingTaskRun.friendlyId,
traceContext: {
traceparent: `00-${existingTaskRun.traceId}-${existingTaskRun.spanId}-01`,
},
diff --git a/apps/webapp/app/v3/services/triggerTask.server.ts b/apps/webapp/app/v3/services/triggerTask.server.ts
index 292c580fc..baf348c6e 100644
--- a/apps/webapp/app/v3/services/triggerTask.server.ts
+++ b/apps/webapp/app/v3/services/triggerTask.server.ts
@@ -33,6 +33,7 @@ export type TriggerTaskServiceOptions = {
scheduleInstanceId?: string;
queueTimestamp?: Date;
overrideCreatedAt?: Date;
+ replayedFromTaskRunFriendlyId?: string;
};
export class OutOfEntitlementError extends Error {
diff --git a/apps/webapp/app/v3/services/triggerTaskV1.server.ts b/apps/webapp/app/v3/services/triggerTaskV1.server.ts
index 5fc09a524..c3ff74dc0 100644
--- a/apps/webapp/app/v3/services/triggerTaskV1.server.ts
+++ b/apps/webapp/app/v3/services/triggerTaskV1.server.ts
@@ -427,6 +427,7 @@ export class TriggerTaskServiceV1 extends BaseService {
parentAttempt?.taskRun.id ??
dependentBatchRun?.dependentTaskAttempt?.taskRun.rootTaskRunId ??
dependentBatchRun?.dependentTaskAttempt?.taskRun.id,
+ replayedFromTaskRunFriendlyId: options.replayedFromTaskRunFriendlyId,
batchId: dependentBatchRun?.id ?? parentBatchRun?.id,
resumeParentOnCompletion: !!(dependentAttempt ?? dependentBatchRun),
depth,
diff --git a/internal-packages/database/prisma/migrations/20250711124003_add_replayed_from_run_friendly_id/migration.sql b/internal-packages/database/prisma/migrations/20250711124003_add_replayed_from_run_friendly_id/migration.sql
new file mode 100644
index 000000000..2578e29f9
--- /dev/null
+++ b/internal-packages/database/prisma/migrations/20250711124003_add_replayed_from_run_friendly_id/migration.sql
@@ -0,0 +1 @@
+ALTER TABLE "TaskRun" ADD COLUMN "replayedFromTaskRunFriendlyId" TEXT;
\ No newline at end of file
diff --git a/internal-packages/database/prisma/schema.prisma b/internal-packages/database/prisma/schema.prisma
index e9c1f99af..3cce55633 100644
--- a/internal-packages/database/prisma/schema.prisma
+++ b/internal-packages/database/prisma/schema.prisma
@@ -648,6 +648,8 @@ model TaskRun {
logsDeletedAt DateTime?
+ replayedFromTaskRunFriendlyId String?
+
/// This represents the original task that that was triggered outside of a Trigger.dev task
rootTaskRun TaskRun? @relation("TaskRootRun", fields: [rootTaskRunId], references: [id], onDelete: SetNull, onUpdate: NoAction)
rootTaskRunId String?
diff --git a/internal-packages/run-engine/src/engine/index.ts b/internal-packages/run-engine/src/engine/index.ts
index 3a97bd2eb..2b4dd77c3 100644
--- a/internal-packages/run-engine/src/engine/index.ts
+++ b/internal-packages/run-engine/src/engine/index.ts
@@ -372,6 +372,7 @@ export class RunEngine {
tags,
parentTaskRunId,
rootTaskRunId,
+ replayedFromTaskRunFriendlyId,
batch,
resumeParentOnCompletion,
depth,
@@ -451,6 +452,7 @@ export class RunEngine {
oneTimeUseToken,
parentTaskRunId,
rootTaskRunId,
+ replayedFromTaskRunFriendlyId,
batchId: batch?.id,
resumeParentOnCompletion,
depth,
diff --git a/internal-packages/run-engine/src/engine/types.ts b/internal-packages/run-engine/src/engine/types.ts
index f9e2abbda..7082ed348 100644
--- a/internal-packages/run-engine/src/engine/types.ts
+++ b/internal-packages/run-engine/src/engine/types.ts
@@ -126,6 +126,7 @@ export type TriggerParams = {
tags: { id: string; name: string }[];
parentTaskRunId?: string;
rootTaskRunId?: string;
+ replayedFromTaskRunFriendlyId?: string;
batch?: {
id: string;
index: number;