Skip to content
Back to skills

Continuum Temporal

ASecurity

Build durable agent workflows with Temporal — sequential/parallel/loop/conditional steps, human-in-the-loop approval gates, custom workflows and activities. Invoke when the user asks "long-running workflow", "approval gate", "human in the loop", "retry on failure", "workflow survives restart", or anything Temporal-related.

  • 85 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added June 4, 2026
ai-agentspythonbashdocker

Works with

  • cli

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned June 4, 2026

npx -y skills add shyftlabs/continuum --skill continuum-temporal --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Continuum Temporal?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Continuum Temporal
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/shyftlabs-continuum-temporal/badge)](https://www.skillsdirectory.com/skills/shyftlabs-continuum-temporal)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: continuum-temporal
description: Build durable agent workflows with Temporal — sequential/parallel/loop/conditional steps, human-in-the-loop approval gates, custom workflows and activities. Invoke when the user asks "long-running workflow", "approval gate", "human in the loop", "retry on failure", "workflow survives restart", or anything Temporal-related.
---

# Continuum Temporal Skill

Authoritative sources: [`docs/temporal/getting-started.md`](../../../docs/temporal/getting-started.md),
[`workflow-patterns.md`](../../../docs/temporal/workflow-patterns.md),
[`custom-agents.md`](../../../docs/temporal/custom-agents.md),
[`custom-workflows.md`](../../../docs/temporal/custom-workflows.md),
[`human-in-loop.md`](../../../docs/temporal/human-in-loop.md),
[`docker.md`](../../../docs/temporal/docker.md).

---

## Setup

```bash
pip install "shyftlabs-continuum[temporal]"
docker compose --profile temporal up -d
```

```env
TEMPORAL_ENABLED=true
TEMPORAL_HOST=localhost:7233
TEMPORAL_NAMESPACE=default
TEMPORAL_TASK_QUEUE=orchestrator-agents
TEMPORAL_ENABLE_HUMAN_IN_LOOP=true
```

---

## Three actors

1. **Worker** — long-running process; polls task queue, executes activities.
2. **Workflow** — declarative durable plan; lives inside Temporal.
3. **Caller** — your app; submits workflows, signals/queries them.

---

## Imports

```python
from orchestrator.temporal import (
    get_temporal_client, get_worker_manager, get_agent_registry,
    WorkflowInput, WorkflowResult,
    AgentStep, ApprovalStep, ParallelStep, ConditionalStep, WaitStep,
    AgentWorkflow, SequentialAgentWorkflow,
    ParallelAgentWorkflow, LoopAgentWorkflow,
    ApprovalDecision, ApprovalRequest,
    HumanInLoopManager, ApprovalNotificationConfig, NotificationParams,
)
```

---

## Hello-Temporal

```python
async def main():
    registry = get_agent_registry()
    registry.register(BaseAgent(name="summarizer", instructions="...", model="gpt-4o-mini"))

    client = get_temporal_client()
    await client.connect()
    await get_worker_manager(client, registry).start()         # blocks

    handle = await client.run_agent_workflow(
        WorkflowInput(
            steps=[
                {"type": "agent",    "agent_name": "summarizer"},
                {"type": "approval", "description": "Review", "approvers": ["alice"]},
                {"type": "agent",    "agent_name": "summarizer"},
            ],
            initial_input="...",
        ),
        id="hello-001",
    )
    result = await handle.result()
    print(result.status, result.content)
```

---

## Step types

| `type` | Schema |
|---|---|
| `"agent"` | `{agent_name, input?, timeout=300, retries=3, metadata}` |
| `"approval"` | `{description, approvers=[], timeout=86400}` |
| `"parallel"` | `{agents: [AgentStep…], merge_strategy: "concatenate"\|"first_success"\|"structured"}` |
| `"conditional"` | `{condition_agent, if_true: [...], if_false: [...]}` |
| `"wait"` | `{duration_seconds: 1..604800}` |

`parse_step(dict) -> WorkflowStep` validates a step dict; raises
`ValueError` on unknown `type`.

---

## Convenience workflows

```python
# Sequential
input_data = SequentialWorkflowInput(
    agent_names=["a", "b", "c"], initial_input="...",
    approval_between_steps=False,
)
await client.start_workflow(SequentialAgentWorkflow.run, input_data)

# Parallel
input_data = ParallelWorkflowInput(
    agent_names=["a", "b", "c"], initial_input="...",
    merge_strategy="structured",
)

# Loop
input_data = LoopWorkflowInput(
    agent_name="reviser", initial_input="...",
    max_iterations=10, termination_phrase="COMPLETE",
)
```

---

## Signals & queries on `AgentWorkflow`

| Signal | |
|---|---|
| `submit_approval(decision: ApprovalDecision)` | Approve / reject / escalate |
| `cancel_workflow()` | Cancel |
| `inject_input(data: dict)` | Inject data mid-flow |

| Query | Returns |
|---|---|
| `get_status()` | `{status, current_step_index, total_steps, completed_steps, cancelled}` |
| `get_pending_approvals()` | `list[dict]` |

---

## Human-in-the-loop

```python
async def notify(params: NotificationParams) -> None:
    if params.type == "approval_required":
        await send_email(...)

get_agent_registry().set_notification_handler(notify)

hlm = HumanInLoopManager(
    client,
    ApprovalNotificationConfig(
        handler=notify,
        timeout_seconds=86400,
        escalation_timeout=7200,
        escalation_handler=on_escalate,
    ),
)

await hlm.approve("workflow-id", request_id="...", decided_by="alice")
await hlm.reject("workflow-id",  request_id="...", decided_by="alice", reason="bad draft")
await hlm.escalate("workflow-id", request_id="...", escalate_to="bob")

pending = await hlm.get_pending_approvals("workflow-id")
status = await hlm.get_workflow_status("workflow-id")
```

---

## Custom workflow + activity

```python
from datetime import timedelta
from temporalio import workflow, activity
from temporalio.common import RetryPolicy

@activity.defn(name="fetch_url_activity")
async def fetch_url_activity(url: str) -> str:
    async with httpx.AsyncClient(timeout=30.0) as c:
        return (await c.get(url)).text

@workflow.defn(sandboxed=False)
class FetchAndSummarizeWorkflow:
    @workflow.run
    async def run(self, url: str) -> WorkflowResult:
        text = await workflow.execute_activity(
            fetch_url_activity, url,
            start_to_close_timeout=timedelta(seconds=60),
            retry_policy=RetryPolicy(maximum_attempts=3),
        )
        result = await workflow.execute_activity(
            "run_agent_activity",
            AgentActivityParams(agent_name="summarizer", input=text),
            start_to_close_timeout=timedelta(seconds=120),
        )
        return WorkflowResult(status="completed", content=result.content)

worker = get_worker_manager(client, registry)
worker.register_workflow(FetchAndSummarizeWorkflow)
worker.register_activity(fetch_url_activity)
await worker.start()
```

---

## Determinism rules (critical!)

In a `@workflow.defn` body:

- ❌ `random.random()`, `uuid.uuid4()`, `datetime.now()`, `time.time()`
- ❌ `requests.get()`, file/DB I/O, third-party SDKs
- ✅ `workflow.uuid4()`, `workflow.random()`, `workflow.now()`
- ✅ `workflow.execute_activity(...)` for I/O
- ✅ `workflow.sleep(...)`, `workflow.wait_condition(...)`
- ✅ `with workflow.unsafe.imports_passed_through():` for type-only imports

---

## Don't

- Don't run I/O in workflow code — push it into an activity.
- Don't reuse a workflow `id` — `WorkflowAlreadyStartedError`.
- Don't forget to register agents with the registry before submitting a
  workflow that references them — `AgentNotRegisteredError`.
- Don't forget `await client.connect()` before `start_workflow(...)`.
- Don't run the worker as a fire-and-forget — `await worker.start()`
  blocks; in production it's its own process.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…