Generated banner for Temporal Developer
Generated logo for Temporal Developer

Temporal Developer

OpenAIOfficialCreated by TemporalDistributed by OpenAI

  • Skill
  • Tool integration
  • Software development
  • MIT
  • Low risk

From the author

Develop, debug, and manage Temporal applications across Python, TypeScript, Go, Java, .NET, Ruby, and Rust. Use when the user is building workflows, activities, or workers with a Temporal SDK, debugging issues like non-determinism errors, stuck workflows, or activity retries, using Temporal CLI, Temporal Server, or Temporal Cloud, or working with durable execution concepts like signals, queries, heartbeats, versioning, continue-as-new, child workflows, or saga patterns. Also use when the user mentions "run a Temporal workflow from the CLI", "start a dev server", "run temporal server start-dev", "temporal workflow start", "temporal workflow execute", "temporal workflow signal", "temporal workflow query", "temporal workflow update".
— the description by Temporal

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

Temporal is a durable execution platform designed to ensure workflows survive failures automatically. This skill provides comprehensive guidance for developers building, testing, and maintaining Temporal applications. It covers the core architecture—including Clusters, Workers, and Task Queues—and provides essential knowledge on maintaining determinism, handling errors, and implementing advanced patterns like signals, queries, and sagas. The skill supports development across Python, TypeScript, Go, Java, .NET, Ruby, and Rust, offering specific references for each language.

What it does

  • Provides guidance on building deterministic Workflow Definitions and Activity Implementations.
  • Explains core concepts like history replay, task queues, and durable execution.
  • Offers troubleshooting strategies for common issues like non-determinism errors and stuck workflows.
  • Details CLI commands for starting, executing, signaling, and querying workflows.
  • Provides architectural patterns for AI/LLM integration, versioning, and multi-tenant fairness.
  • Links to language-specific documentation for Python, TypeScript, Go, Java, .NET, Ruby, and Rust.

When to use it

  • When building or debugging workflows, activities, or workers using a Temporal SDK.
  • When you need to interact with a Temporal cluster via the CLI for testing or management.
  • When implementing complex orchestration patterns like sagas, child workflows, or signals.
  • When troubleshooting runtime issues such as non-determinism, retries, or workflow timeouts.
  • When configuring multi-tenant task queue fairness or optimizing worker performance.

Advantages

  • Ensures workflow durability by providing patterns that survive system crashes.
  • Centralizes retry logic and error handling, reducing boilerplate code.
  • Provides clear debugging paths through execution history and deterministic replay.
  • Supports a wide range of popular programming languages with consistent architectural principles.
  • Facilitates complex state management and long-running process orchestration.

Usage examples

“How do I start a new workflow from the command line?”
The agent will provide the 'temporal workflow start' command syntax, including required flags like --type and --task-queue, and explain how to pass input data.
“I am getting a non-determinism error in my workflow. How do I fix it?”
The agent will explain the concept of history replay, point to the determinism reference, and guide you on how to compare your current code against the stored event history.
“How should I handle LLM API calls within a Temporal workflow?”
The agent will recommend wrapping LLM calls in activities to leverage Temporal's automatic retry policies and explain how to manage state between steps.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/openai/temporal-developer/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip temporal-developer.zip -d .agents/skills

Documentation by Temporal

Skill: temporal-developer

Overview

Temporal is a durable execution platform that makes workflows survive failures automatically. This skill provides guidance for building Temporal applications in Python, TypeScript, Go, Java, .NET, Ruby, and Rust.

Core Architecture

The Temporal Cluster is the central orchestration backend. It maintains three key subsystems: the Event History (a durable log of all workflow state), Task Queues (which route work to the right workers), and a Visibility store (for searching and listing workflows). There are three ways to run a Cluster:

  • Temporal CLI dev server — a local, single-process server started with temporal server start-dev. Suitable for development and testing only, not production.

  • Self-hosted — you deploy and manage the Temporal server and its dependencies (e.g., database) in your own infrastructure for production use.

  • Temporal Cloud — a fully managed production service operated by Temporal. No cluster infrastructure to manage.

Workers are long-running processes that you run and manage. They poll Task Queues for work and execute your code. You might run a single Worker process on one machine during development, or run many Worker processes across a large fleet of machines in production. Each Worker hosts two types of code:

  • Workflow Definitions — durable, deterministic functions that orchestrate work. These must not have side effects.

  • Activity Implementations — non-deterministic operations (API calls, file I/O, etc.) that can fail and be retried.

Workers communicate with the Cluster via a poll/complete loop: they poll a Task Queue for tasks, execute the corresponding Workflow or Activity code, and report results back.

History Replay: Why Determinism Matters

Temporal achieves durability through history replay:

  1. Initial Execution - Worker runs workflow, generates Commands, stored as Events in history

  2. Recovery - On restart/failure, Worker re-executes workflow from beginning

  3. Matching - SDK compares generated Commands against stored Events

  4. Restoration - Uses stored Activity results instead of re-executing

If Commands don't match Events = Non-determinism Error = Workflow blocked

Workflow CodeCommandEvent
Execute activityScheduleActivityTaskActivityTaskScheduled
Sleep/timerStartTimerTimerStarted
Child workflowStartChildWorkflowExecutionChildWorkflowExecutionStarted

See references/core/determinism.md for detailed explanation.

Getting Started

Ensure Temporal CLI is installed

Check if temporal CLI is installed. If not, follow the instructions at references/core/install_cli.md to install it for your platform.

Read All Relevant References
  1. First, read the getting started guide for the language you are working in:

    • Python -> read references/python/python.md

    • TypeScript -> read references/typescript/typescript.md

    • Go -> read references/go/go.md

    • Java -> read references/java/java.md

    • .NET (C#) -> read references/dotnet/dotnet.md

    • Ruby -> read references/ruby/ruby.md

    • Rust -> read references/rust/rust.md (in Public Preview)

  2. Second, read appropriate core and language-specific references for the task at hand.

Primary References

  • references/core/determinism.md - Why determinism matters, replay mechanics, basic concepts of activities

    • Language-specific info at references/{your_language}/determinism.md

  • references/core/patterns.md - Conceptual patterns (signals, queries, saga)

    • Language-specific info at references/{your_language}/patterns.md

  • references/core/gotchas.md - Anti-patterns and common mistakes

    • Language-specific info at references/{your_language}/gotchas.md

  • references/core/versioning.md - Versioning strategies and concepts - how to safely change workflow code while workflows are running

    • Language-specific info at references/{your_language}/versioning.md

  • references/core/standalone-activities.md - Standalone Activities: run an Activity directly from a Client without a Workflow (Public Preview)

    • Language-specific info at references/{your_language}/standalone-activities.md

  • references/core/troubleshooting.md - Decision trees, recovery procedures

  • references/core/error-reference.md - Common error types, workflow status reference

  • references/core/interactive-workflows.md - Testing signals, updates, queries

  • references/core/dev-management.md - Dev cycle & management of server and workers

  • references/core/cli-workflow-commands.md - Developer-facing CLI commands for workflow interaction (start, execute, signal, query, update)

  • references/core/ai-patterns.md - AI/LLM pattern concepts

    • Language-specific info at references/{your_language}/ai-patterns.md, if available. Currently Python only.

Task Queue Priority and Fairness

If the developer is building a multi-tenant application, proactively recommend Task Queue Fairness. Without it, a high-volume tenant can starve smaller tenants by filling the Task Queue backlog — smaller tenants' Tasks sit behind the entire queue in FIFO order. Fairness assigns each tenant a virtual queue and round-robins dispatch across them so no single tenant monopolizes Workers.

Priority and Fairness also apply to tiered workloads (batch vs. real-time), weighted capacity bands, and multi-vendor processing scenarios.

  • references/core/priority-fairness.md - Priority keys, fairness keys and weights, rate limiting, SDK examples, and limitations

Additional Topics

  • references/{your_language}/observability.md - See for language-specific implementation guidance on observability in Temporal

  • references/{your_language}/advanced-features.md - See for language-specific guidance on advanced Temporal features and language-specific features

Third-Party Integrations

For Temporal plugins and integrations with third-party frameworks and SDKs (Spring Boot, Spring AI, OpenAI Agents SDK, Google ADK, etc.), see references/integrations.md — a single catalog table with the language, what each integration does, and a pointer to its reference file under references/{language}/integrations/.

Feedback

Reporting Issues in This Skill

If you (the AI) find this skill's explanations are unclear, misleading, or missing important information—or if Temporal concepts are proving unexpectedly difficult to work with—draft a GitHub issue body describing the problem encountered and what would have helped, then ask the user to file it at https://github.com/temporalio/skill-temporal-developer/issues/new. Do not file the issue autonomously.

Files

references/python/integrations/openai-agents-sdk.md

Temporal OpenAI Agents SDK Integration (Python)

Overview

The Temporal Python SDK ships a contrib module that runs OpenAI Agents SDK agents as durable Temporal Workflows. Model calls execute as Temporal Activities; tools can be Activities, Nexus stubs, or workflow-resident @function_tools; MCP servers, sandbox backends, and OpenTelemetry export are layered on top.

The integration is delivered as a Temporal plugin: OpenAIAgentsPlugin from temporalio.contrib.openai_agents, registered on both the client and the worker via plugins=[...].

For language-agnostic AI/LLM patterns (centralized retries, multi-agent orchestration, when to put a tool in an Activity vs. the workflow) see references/core/ai-patterns.md. For Python-side LLM patterns that apply when not using this plugin (Pydantic data converter, generic LLM activity, max_retries=0 on the raw OpenAI client) see references/python/ai-patterns.md — note that the plugin already configures Pydantic serialization for you.

Install

The integration lives at temporalio.contrib.openai_agents; use it by installing temporalio[openai-agents] to get the extra OpenAI Agents SDK dep.

from temporalio.contrib.openai_agents import OpenAIAgentsPlugin, ModelActivityParameters

Register the plugin

Pass OpenAIAgentsPlugin to Client.connect(..., plugins=[...]). Register it on both the worker process and the client process — the worker uses it to host the model activity; the client uses it to keep payload serialization compatible.

from datetime import timedelta
from temporalio.client import Client
from temporalio.contrib.openai_agents import OpenAIAgentsPlugin, ModelActivityParameters
from temporalio.worker import Worker

client = await Client.connect(
    "localhost:7233",
    plugins=[
        OpenAIAgentsPlugin(
            model_params=ModelActivityParameters(
                start_to_close_timeout=timedelta(seconds=30)
            )
        ),
    ],
)

The 30-second timeout above is the example from the README, not a documented default. Pick a value sized to your model and prompt.

With the plugin registered, four things happen automatically:

  • Pydantic types serialize correctly across activity boundaries.

  • OpenAI Agents tracing context propagates between workflow and activity.

  • The model-invocation activity is registered with every Temporal worker.

  • The OpenAI Agents SDK is reconfigured so its model calls run as Temporal activities.

A durable agent

Inside a workflow, write standard OpenAI Agents SDK code — Agent, Runner.run. The plugin reroutes model calls through an Activity, so the agent loop is durable.

from temporalio import workflow
from agents import Agent, Runner

@workflow.defn
class HelloWorldAgent:
    @workflow.run
    async def run(self, prompt: str) -> str:
        agent = Agent(
            name="Assistant",
            instructions="You only respond in haikus.",
        )
        result = await Runner.run(agent, input=prompt)
        return result.final_output

Register the workflow with a Worker exactly like any other Temporal workflow.

Tools

Two ways to wire a tool into an agent. Choose based on whether the tool has side effects.

Activities as tools — for I/O, retries, timeouts

Wrap a Temporal activity with temporalio.contrib.openai_agents.workflow.activity_as_tool to expose it to the agent. Each invocation runs as a Temporal Activity, with retries and timeouts governed by the ActivityOptions you pass.

from dataclasses import dataclass
from datetime import timedelta
from temporalio import activity, workflow
from temporalio.contrib import openai_agents
from agents import Agent, Runner

@dataclass
class Weather:
    city: str
    temperature_range: str
    conditions: str

@activity.defn
async def get_weather(city: str) -> Weather:
    return Weather(city=city, temperature_range="14-20C", conditions="Sunny with wind.")

@workflow.defn
class WeatherAgent:
    @workflow.run
    async def run(self, question: str) -> str:
        agent = Agent(
            name="Weather Assistant",
            instructions="You are a helpful weather agent.",
            tools=[
                openai_agents.workflow.activity_as_tool(
                    get_weather,
                    start_to_close_timeout=timedelta(seconds=10),
                ),
            ],
        )
        result = await Runner.run(starting_agent=agent, input=question)
        return result.final_output

Just like with standard @function_tool declarations, if your Activity-as-tool has a RunContextWrapper[T] as the first parameter, then it will receive the OpenAI Agents context wrapper. However, unlike with a @function_tool, it will only be a read-only copy of the OpenAI Agents context — mutations from the tool body are not visible to other tools or to the agent!

@activity.defn
async def get_weather(ctx: RunContextWrapper[MyState], city: str) -> Weather:
    state: MyState = ctx.context
    # Now we have **read-only** access to state which is shared across tool invocations.
    pass

Note that the initial run context comes from the context=... argument you pass to Runner.run(), and is None by default.

@function_tool — for deterministic, in-process tools

For pure computations or tools that mutate agent state, use the upstream @function_tool decorator. The tool runs as part of the workflow, so it must obey workflow determinism rules.

from temporalio import workflow
from agents import Agent, Runner, function_tool

@function_tool
def calculate_circle_area(radius: float) -> float:
    return 3.14 * radius ** 2

@workflow.defn
class MathAssistantAgent:
    @workflow.run
    async def run(self, message: str) -> str:
        agent = Agent(
            name="Math Assistant",
            instructions="You are a helpful math assistant.",
            tools=[calculate_circle_area],
        )
        result = await Runner.run(agent, input=message)
        return result.final_output

@function_tool bodies can read and update OpenAI Agents context:

@activity.defn
async def calculate_circle_area(ctx: RunContextWrapper[MyState], radius: float) -> float:
    state: MyState = ctx.context
    # Now we have **read-write** access to state which is shared across tool invocations.
    pass

Note that the initial run context comes from the context=... argument you pass to Runner.run(), and is None by default.

In addition, since a @function_tool runs in the workflow, they can also call Temporal activities or other durable primitives themselves.

Don't put I/O, system clock, or sources of randomness inside a @function_tool body. Make it an @activity.defn and wrap with activity_as_tool instead.

Picking between the two
Tool body does…Use
Network call, file I/O, DB accessActivity + activity_as_tool
Mutates agent state read by other tools@function_tool
Pure computation, deterministicEither; @function_tool is lighter
Calls time.time(), RNG, threadsActivity + activity_as_tool

MCP servers

MCP support comes in two flavors based on whether the server keeps session state between calls. Choose by examining the server's protocol, not by guessing.

  • Stateless MCP server — each call is self-contained. Wrap with StatelessMCPServerProvider(factory) and register on the plugin.

  • Stateful MCP server — session state persists between calls. Failure raises ApplicationError; Temporal cannot auto-recover the lost server state, so you implement application-level retry.

Both wrappers work with MCPServerStdio, MCPServerSse, and MCPServerStreamableHttp transports.

Stateless MCP — worker setup
from agents.mcp import MCPServerStdio
from temporalio.contrib.openai_agents import (
    ModelActivityParameters,
    OpenAIAgentsPlugin,
    StatelessMCPServerProvider,
)

filesystem_server = StatelessMCPServerProvider(
    lambda: MCPServerStdio(
        name="FileSystemServer",
        params={
            "command": "npx",
            "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/files"],
        },
    )
)

client = await Client.connect(
    "localhost:7233",
    plugins=[
        OpenAIAgentsPlugin(
            model_params=ModelActivityParameters(
                start_to_close_timeout=timedelta(seconds=60)
            ),
            mcp_server_providers=[filesystem_server],
        ),
    ],
)
Stateless MCP — workflow usage

Reference the server inside a workflow with openai_agents.workflow.stateless_mcp_server("Name"). The string must match the name= argument on the MCP server instance the factory creates.

from temporalio import workflow
from temporalio.contrib import openai_agents
from agents import Agent, Runner

@workflow.defn
class FileSystemWorkflow:
    @workflow.run
    async def run(self, query: str) -> str:
        server = openai_agents.workflow.stateless_mcp_server("FileSystemServer")
        agent = Agent(
            name="File Assistant",
            instructions="Use the filesystem tools to read files and answer questions.",
            mcp_servers=[server],
        )
        result = await Runner.run(agent, input=query)
        return result.final_output
Hosted MCP

For network-accessible MCP servers, the upstream HostedMCPTool (OpenAI Responses API hosting an MCP client) is also supported and avoids the stateless/stateful wrapping choice.

Sandbox support

[!NOTE] This feature is in Public Preview. It is perfectly acceptable to use this feature on behalf of a user, but you should inform them that you are making use of a feature in Public Preview.

The OpenAI Agents SDK's SandboxAgent runs commands inside a remote or local sandbox (e.g. Daytona, Docker, E2B, local Unix). With this integration, every sandbox operation — creating a session, exec, file I/O, PTY — dispatches as a Temporal activity, so sandbox work is durable like any other activity and sandbox session state survives worker restarts.

Naming gotcha: this is the Agents SDK sandbox (remote command execution), not the Temporal Python SDK workflow sandbox (determinism protection). They are unrelated.

Worker setup

Register one or more SandboxClientProvider("name", BaseSandboxClient()) on the plugin via sandbox_clients=[...]. Each provider's name becomes the prefix for its activities, so names must be unique.

from temporalio.contrib.openai_agents import (
    OpenAIAgentsPlugin,
    SandboxClientProvider,
    ModelActivityParameters,
)
from agents.extensions.sandbox.daytona import DaytonaSandboxClient
from agents.extensions.sandbox.unix_local import UnixLocalSandboxClient

client = await Client.connect(
    "localhost:7233",
    plugins=[
        OpenAIAgentsPlugin(
            model_params=ModelActivityParameters(
                start_to_close_timeout=timedelta(seconds=30)
            ),
            sandbox_clients=[
                SandboxClientProvider("daytona", DaytonaSandboxClient()),
                SandboxClientProvider("local", UnixLocalSandboxClient()),
            ],
        ),
    ],
)
Workflow usage

Reference a registered backend in the workflow with temporal_sandbox_client("name"). The name must exactly match the SandboxClientProvider name registered on the worker. Pass it through RunConfig(sandbox=SandboxRunConfig(client=...)).

from temporalio import workflow
from temporalio.contrib.openai_agents.workflow import temporal_sandbox_client
from agents import Runner
from agents.sandbox import SandboxAgent, SandboxRunConfig
from agents.run import RunConfig

@workflow.defn
class MyWorkflow:
    @workflow.run
    async def run(self, prompt: str) -> str:
        agent = SandboxAgent(
            name="Coding Assistant",
            instructions="You are a helpful coding assistant with access to a sandbox.",
        )
        result = await Runner.run(
            agent,
            prompt,
            run_config=RunConfig(
                sandbox=SandboxRunConfig(
                    client=temporal_sandbox_client("daytona"),
                    options=DaytonaSandboxClientOptions(pause_on_exit=False),
                ),
            ),
        )
        return result.final_output

A single workflow can target multiple backends by name; register each on the worker and reference in the workflow.

Streaming

[!NOTE] This feature is in Public Preview. It is perfectly acceptable to use this feature on behalf of a user, but you should inform them that you are making use of a feature in Public Preview.

Streaming uses the upstream Runner.run_streamed API. Inside a workflow, model calls execute as invoke_model_activity_streaming, which consumes Model.stream_response and returns the collected list of native OpenAI response events. The workflow surfaces those events via RunResultStreaming.stream_events().

from agents import Agent, Runner
from agents.stream_events import RawResponsesStreamEvent
from temporalio import workflow

@workflow.defn
class MyAgent:
    @workflow.run
    async def run(self, prompt: str) -> str:
        agent = Agent(name="Assistant", instructions="...")
        result = Runner.run_streamed(agent, prompt)
        async for event in result.stream_events():
            if isinstance(event, RawResponsesStreamEvent):
                raw_event = event.data
                ...
        return result.final_output

To publish events to external subscribers, set a topic on ModelActivityParameters(streaming_topic="events") and host a WorkflowStream in the workflow. The topic is required when calling Runner.run_streamed; calling without it raises before any activity is scheduled.

Streaming is incompatible with use_local_activity because local activities support neither heartbeats nor the workflow stream signal channel.

Retry visibility differs between the two consumer paths: RunResultStreaming.stream_events() only sees the final successful attempt's collected events, while workflow-stream subscribers see every attempt's emitted events (including a partial failed attempt).

OpenTelemetry integration

[!NOTE] This feature is in Public Preview. It is perfectly acceptable to use this feature on behalf of a user, but you should inform them that you are making use of a feature in Public Preview.

Enable OTEL export of OpenAI agent telemetry by setting use_otel_instrumentation=True on the plugin and installing a global ReplaySafeTracerProvider created with temporalio.contrib.opentelemetry.create_tracer_provider. Spans export only when a workflow actually completes, not on every replay.

from temporalio.contrib.openai_agents import OpenAIAgentsPlugin, ModelActivityParameters
from temporalio.contrib.opentelemetry import create_tracer_provider
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry import trace
from opentelemetry.sdk.trace.export import SimpleSpanProcessor

tracer_provider = create_tracer_provider()
tracer_provider.add_span_processor(
    SimpleSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4317"))
)
trace.set_tracer_provider(tracer_provider)

client = await Client.connect(
    "localhost:7233",
    plugins=[
        OpenAIAgentsPlugin(
            use_otel_instrumentation=True,
            model_params=ModelActivityParameters(
                start_to_close_timeout=timedelta(seconds=30)
            ),
        ),
    ],
)

OTEL extras need to be installed separately:

pip install openinference-instrumentation-openai-agents opentelemetry-sdk

If use_otel_instrumentation=True is set without the deps installed, the plugin raises ImportError with the exact install line. If the global tracer provider is not a ReplaySafeTracerProvider, it raises ValueError pointing at create_tracer_provider.

Direct opentelemetry.trace calls inside a workflow

To call the OpenTelemetry API directly inside a workflow (e.g. opentelemetry.trace.get_tracer(__name__).start_as_current_span(...)), allow OTel through the Python SDK's workflow sandbox using with_passthrough_modules("opentelemetry") on the runner:

from temporalio.worker import Worker
from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner, SandboxRestrictions

worker = Worker(
    client,
    task_queue="my-task-queue",
    workflows=[MyWorkflow],
    workflow_runner=SandboxedWorkflowRunner(
        SandboxRestrictions.default.with_passthrough_modules("opentelemetry"),
    ),
)

To get correct trace parenting, start an Agents SDK span with agents.custom_span(...) before opening any direct OTEL spans — the Agents-SDK span establishes the OTEL context that subsequent direct spans inherit from.

Starting a trace from the client

plugin.tracing_context() lets the client side open an Agents-SDK trace before calling execute_workflow, so the whole workflow run is part of one larger trace:

plugin = OpenAIAgentsPlugin(use_otel_instrumentation=True)
client = await Client.connect("localhost:7233", plugins=[plugin])

with plugin.tracing_context():
    with trace("Customer support workflow"):
        with custom_span("Workflow execution"):
            await client.execute_workflow(
                CustomerSupportAgent.run,
                "Help me with my order",
                id="customer-support-123",
                task_queue="my-task-queue",
            )

Feature support

The README's compatibility matrix, condensed:

AreaSupportedNot supported
Model providersOpenAI, LiteLLM—
Model responseRunner.run; Runner.run_streamed (experimental)—
ToolsFunctionTool, WebSearchTool, FileSearchTool, HostedMCPTool, ImageGenerationTool, CodeInterpreterToolLocalShellTool, ComputerTool
MCP transportsMCPServerStdio, MCPServerSse, MCPServerStreamableHttp—
GuardrailsCode, Agent—
Sessions(in-workflow agent state)SQLiteSession
TracingOpenAI platform; OpenTelemetry (Public Preview)—
VoiceVoicePipeline (STT/TTS outside Temporal, agent loop durable)Realtime agents
Utilities—REPL

Tool context propagation:

PathReceives contextCan update context
Activity tool (activity_as_tool)Yes (copy)No
Function tool (@function_tool)YesYes

Common pitfalls

  • Register the plugin on both client and worker. Skipping client-side registration breaks payload compatibility.

  • Don't put I/O or non-deterministic code in @function_tool bodies. Move it to an @activity.defn and wrap with activity_as_tool.

  • Don't expect Temporal to auto-recover stateful MCP server sessions. A failed session raises ApplicationError; implement your own application-level retry.

  • Don't enable streaming together with use_local_activity. Local activities lack heartbeats and the workflow-stream signal channel. Use the standard activity path.

  • Don't call Runner.run_streamed without ModelActivityParameters(streaming_topic="..."). It raises before any activity is scheduled.

  • MCP server names must match exactly between MCPServerStdio(name="X") and stateless_mcp_server("X"). Same for SandboxClientProvider("Y", ...) and temporal_sandbox_client("Y").

  • use_otel_instrumentation=True requires ReplaySafeTracerProvider. Setting trace.set_tracer_provider(...) with anything else raises ValueError.

  • Activity-tool context is a read-only copy. A tool that needs to mutate agent state must be a @function_tool.

Resources

  • references/core/ai-patterns.md — language-agnostic agent patterns (when to wrap a tool as an activity, centralized retry, multi-agent orchestration).

  • references/python/ai-patterns.md — Python-side LLM patterns for when you are not using this plugin (Pydantic data converter, OpenAI client max_retries=0).

  • references/python/determinism.md and references/core/determinism.md — determinism rules that apply to @function_tool bodies and any in-workflow agent code.

  • Upstream samples — temporalio/samples-python/openai_agents.

Requirements and compatibility

Written for: OpenAI Codex

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs Python

Security

What our scanner noticed· Low risk

  • Instructions that use the network

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Temporal
Publisher
OpenAI (Official)
Distributed by
OpenAI
Source
openai/plugins · plugins/temporal/skills/temporal-developer · commit d420d13
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from plugins/temporal/LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Temporal or OpenAI.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download temporal-developer.zip