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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ __pycache__/
*.pyo
*.egg-info/
.pytest_cache/
.agent-relay/

.sst
openclaw-web/sst-env.d.ts
59 changes: 59 additions & 0 deletions .trajectories/completed/traj_1773123201611_9e34005f.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"id": "traj_1773123201611_9e34005f",
"version": 1,
"task": {
"title": "test run #cd590290",
"source": {
"system": "workflow-runner",
"id": "cd590290340c324223857873"
}
},
"status": "completed",
"startedAt": "2026-03-10T06:13:21.611Z",
"agents": [
{
"name": "orchestrator",
"role": "workflow-runner",
"joinedAt": "2026-03-10T06:13:21.611Z"
}
],
"chapters": [
{
"id": "ch_2902721b",
"title": "Planning",
"agentName": "orchestrator",
"startedAt": "2026-03-10T06:13:21.611Z",
"events": [
{
"ts": 1773123201611,
"type": "note",
"content": "Approach: 1-step dag workflow — Parsed 1 steps, DAG validated, no cycles"
}
],
"endedAt": "2026-03-10T06:13:25.182Z"
},
{
"id": "ch_3163e0ca",
"title": "Retrospective",
"agentName": "orchestrator",
"startedAt": "2026-03-10T06:13:25.182Z",
"events": [
{
"ts": 1773123205182,
"type": "reflection",
"content": "All 1 steps completed in 4s. (completed in 4 seconds)",
"significance": "high"
}
],
"endedAt": "2026-03-10T06:13:25.182Z"
}
],
"completedAt": "2026-03-10T06:13:25.182Z",
"retrospective": {
"summary": "All 1 steps completed in 4s.",
"approach": "dag workflow (0 agents)",
"confidence": 0.75,
"learnings": [],
"challenges": []
}
}
89 changes: 89 additions & 0 deletions .trajectories/completed/traj_1773123224392_b3a22ec2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
{
"id": "traj_1773123224392_b3a22ec2",
"version": 1,
"task": {
"title": "cross-repo-analysis run #fc23c441",
"source": {
"system": "workflow-runner",
"id": "fc23c441426d5520b8dbfe65"
}
},
"status": "abandoned",
"startedAt": "2026-03-10T06:13:44.392Z",
"agents": [
{
"name": "orchestrator",
"role": "workflow-runner",
"joinedAt": "2026-03-10T06:13:44.392Z"
},
{
"name": "analyzer",
"role": "analyzer",
"joinedAt": "2026-03-10T06:13:47.954Z"
}
],
"chapters": [
{
"id": "ch_8b144dd2",
"title": "Planning",
"agentName": "orchestrator",
"startedAt": "2026-03-10T06:13:44.392Z",
"events": [
{
"ts": 1773123224392,
"type": "note",
"content": "Purpose: E2E test for paths and workdir features (PR"
},
{
"ts": 1773123224392,
"type": "note",
"content": "Approach: 2-step dag workflow — Parsed 2 steps, 1 dependent steps, DAG validated, no cycles"
},
{
"ts": 1773123227954,
"type": "note",
"content": "\"check-relaycast\": List the top-level files in this directory and report what project this is",
"raw": {
"agent": "analyzer"
}
},
{
"ts": 1773123240141,
"type": "error",
"content": "\"check-relaycast\" failed [verification_mismatch]: Agent completed but did not output the expected sentinel \"RELAYCAST_CHECKED\". The task prompt may not clearly specify the required output format, or the agent produced correct work but did not emit the signal.",
"significance": "high",
"raw": {
"cause": "verification_mismatch",
"rawError": "Verification failed for \"check-relaycast\": output does not contain \"RELAYCAST_CHECKED\" (token found only in task injection — agent must output it explicitly)",
"attempt": 1,
"maxRetries": 0
}
},
{
"ts": 1773123240143,
"type": "note",
"content": "\"check-dashboard\" skipped — Upstream dependency \"check-relaycast\" failed"
},
{
"ts": 1773123240143,
"type": "decision",
"content": "Whether to skip check-dashboard → skip: Upstream dependency \"check-relaycast\" failed",
"significance": "medium",
"raw": {
"question": "Whether to skip check-dashboard",
"chosen": "skip",
"reasoning": "Upstream dependency \"check-relaycast\" failed"
}
},
{
"ts": 1773123240143,
"type": "error",
"content": "Workflow abandoned: Step \"check-relaycast\" failed: Step \"check-relaycast\" failed after 0 retries: Verification failed for \"check-relaycast\": output does not contain \"RELAYCAST_CHECKED\" (token found only in task injection — agent must output it explicitly)",
"significance": "high"
}
],
"endedAt": "2026-03-10T06:14:00.143Z"
}
],
"completedAt": "2026-03-10T06:14:00.143Z"
}
97 changes: 97 additions & 0 deletions .trajectories/completed/traj_1773123294482_756d93a6.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
{
"id": "traj_1773123294482_756d93a6",
"version": 1,
"task": {
"title": "cross-repo-analysis run #ee39e6c4",
"source": {
"system": "workflow-runner",
"id": "ee39e6c435a567f189511078"
}
},
"status": "completed",
"startedAt": "2026-03-10T06:14:54.482Z",
"agents": [
{
"name": "orchestrator",
"role": "workflow-runner",
"joinedAt": "2026-03-10T06:14:54.482Z"
},
{
"name": "analyzer",
"role": "analyzer",
"joinedAt": "2026-03-10T06:14:58.034Z"
}
],
"chapters": [
{
"id": "ch_ce1d459e",
"title": "Planning",
"agentName": "orchestrator",
"startedAt": "2026-03-10T06:14:54.482Z",
"events": [
{
"ts": 1773123294482,
"type": "note",
"content": "Purpose: E2E test for paths and workdir features (PR"
},
{
"ts": 1773123294482,
"type": "note",
"content": "Approach: 2-step dag workflow — Parsed 2 steps, 1 dependent steps, DAG validated, no cycles"
},
{
"ts": 1773123298034,
"type": "note",
"content": "\"check-relaycast\": Run `pwd` and `ls` in the current directory",
"raw": {
"agent": "analyzer"
}
},
{
"ts": 1773123312835,
"type": "finding",
"content": "\"check-relaycast\" completed → RELAY_SDK_VERIFIED",
"significance": "medium"
},
{
"ts": 1773123312836,
"type": "note",
"content": "\"check-dashboard\": Run `pwd` and `ls` in the current directory",
"raw": {
"agent": "analyzer"
}
},
{
"ts": 1773123317522,
"type": "finding",
"content": "\"check-dashboard\" completed → DASH_VERIFIED",
"significance": "medium"
}
],
"endedAt": "2026-03-10T06:15:17.523Z"
},
{
"id": "ch_9bd24134",
"title": "Retrospective",
"agentName": "orchestrator",
"startedAt": "2026-03-10T06:15:17.523Z",
"events": [
{
"ts": 1773123317523,
"type": "reflection",
"content": "All 2 steps completed in 23s. (completed in 23 seconds)",
"significance": "high"
}
],
"endedAt": "2026-03-10T06:15:17.523Z"
}
],
"completedAt": "2026-03-10T06:15:17.523Z",
"retrospective": {
"summary": "All 2 steps completed in 23s.",
"approach": "dag workflow (1 agents)",
"confidence": 1,
"learnings": [],
"challenges": []
}
}
2 changes: 2 additions & 0 deletions packages/sdk-py/src/agent_relay/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
SwarmPattern,
AgentDefinition,
AgentConstraints,
PathDefinition,
RelayYamlConfig,
AgentCli,
IdleNudgeConfig,
Expand Down Expand Up @@ -128,6 +129,7 @@
"SwarmPattern",
"AgentDefinition",
"AgentConstraints",
"PathDefinition",
"RelayYamlConfig",
"AgentCli",
"IdleNudgeConfig",
Expand Down
33 changes: 33 additions & 0 deletions packages/sdk-py/src/agent_relay/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,24 @@ def to_dict(self) -> dict[str, Any]:
return result


@dataclass
class PathDefinition:
"""A named path to an external directory for cross-repo workflows."""

name: str
path: str
description: str | None = None
required: bool | None = None

def to_dict(self) -> dict[str, Any]:
result: dict[str, Any] = {"name": self.name, "path": self.path}
if self.description is not None:
result["description"] = self.description
if self.required is not None:
result["required"] = self.required
return result


@dataclass
class AgentDefinition:
name: str
Expand All @@ -132,6 +150,9 @@ class AgentDefinition:
channels: list[str] | None = None
constraints: AgentConstraints | None = None
interactive: bool | None = None
cwd: str | None = None
workdir: str | None = None
additional_paths: list[str] | None = None

def to_dict(self) -> dict[str, Any]:
result: dict[str, Any] = {
Expand All @@ -150,6 +171,12 @@ def to_dict(self) -> dict[str, Any]:
result["constraints"] = constraints
if self.interactive is not None:
result["interactive"] = self.interactive
if self.cwd is not None:
result["cwd"] = self.cwd
if self.workdir is not None:
result["workdir"] = self.workdir
if self.additional_paths is not None:
result["additionalPaths"] = self.additional_paths
return result


Expand All @@ -175,6 +202,7 @@ class WorkflowStep:
verification: VerificationCheck | None = None
timeout_ms: int | None = None
retries: int | None = None
workdir: str | None = None

def to_dict(self) -> dict[str, Any]:
result: dict[str, Any] = {
Expand All @@ -190,6 +218,8 @@ def to_dict(self) -> dict[str, Any]:
result["timeoutMs"] = self.timeout_ms
if self.retries is not None:
result["retries"] = self.retries
if self.workdir is not None:
result["workdir"] = self.workdir
return result


Expand Down Expand Up @@ -285,6 +315,7 @@ class RelayYamlConfig:
agents: list[AgentDefinition]
version: str = "1.0"
description: str | None = None
paths: list[PathDefinition] | None = None
workflows: list[WorkflowDefinition] | None = None
coordination: CoordinationConfig | None = None
state: StateConfig | None = None
Expand All @@ -300,6 +331,8 @@ def to_dict(self) -> dict[str, Any]:
}
if self.description is not None:
result["description"] = self.description
if self.paths is not None:
result["paths"] = [p.to_dict() for p in self.paths]
if self.workflows is not None:
result["workflows"] = [workflow.to_dict() for workflow in self.workflows]
if self.coordination is not None:
Expand Down
Loading
Loading