* Add initial skill for testing, which is simply Steve's skill (#1) * Add initial skill for testing, which is simply Steve's skill * Rename skill to 'temporal-dev' and update version Updated skill name and version for Temporal Python. * Use claude to merge Steve's, Max's, and Mason's skills. (#2) * Use claude to merge Steve's, Max's, and Mason's skills. Did a review pass using claude's skill devlopment skills * Add missing things from Steve * trigger tweaks * Add in common gotchas from Johann * add simple feedback mechanism (#3) * Change skill name to kebab-case, for compatibility with Amp and Cline (#7) * Clean up references/core/ai-integration.md * Clean up references/core/common-gotchas.md * Clean up references/core/common-gotchas.md * Clean up references/core/determinism.md * Clean up references/core/determinism.md * Update error-reference.md * Update interactive-workflows.md * Clean up patterns.md * Cut shell scripts * Edit troubleshooting.md * remove interceptors for now * remove dynamic workflows * clarify on heartbeating of async activity completions, and prompt it a bit in relation to signals * Improve references/python/advanced-features.md * Use explicit namespace in connect * remove duplicated content from determinism.md, clean up * Improve references/python/data-handling.md * Prefer start_to_close_timeout * don't explicitely provide defaults for retry policies * error-handling.md cleanup * move idempotency patterns to patterns.md * remove multi-param activities * small edits * Unify sandbox stuff into one file * local activities aren't experimental * Clean up references/python/sync-vs-async.md * Cleanup observability.md, remove duplicated search attributes * Cut otel for now * cut a lot of duplicate stuff from python gotchas, address comments * de-duplicate content * Lots of improvements to testing * cleanup to top level of skill (like CLI install instructions), and to top-level of python * Improve patterns.md * clean up ai-patterns.md * Update readme with installation instructions * remove ts directory * De-couple core from python and TypeScript as much as possible * Remove TypeScript hints * add prompting for feedback at startup - wait for ethan on slack channel * shorten url * Update slack channel * Automated pass over on python cleanup & deduplication * Remove multi-patching from Python, since its obvious, dont waste tokens on it. (#34) * Add TypeScript (#31) Adds initial support for TypeScript to the skill --------- Co-authored-by: James Watkins-Harvey <mjameswh@users.noreply.github.com> Co-authored-by: Chris Olszewski <chrisdolszewski@gmail.com> * Fix typos and reference links (#36) * Fix typos and reference links * 2 more typo fixes * quick edit to readme (#37) * Fix saga compensations to run under cancellation protection (#43) When a workflow is cancelled mid-saga, compensations must run in a cancellation-protected scope, otherwise they are immediately cancelled before they can execute. - Python: wrap compensation loop in asyncio.shield() so it runs even when the workflow receives a CancelledError - TypeScript: wrap compensation loop in CancellationScope.nonCancellable() so it runs even when the root scope is cancelled (per official docs: "Cleanup logic must be in a nonCancellable scope") - TypeScript: also fix compensation registration order — register BEFORE calling the activity (was already correct in Python) Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> * Update readme for public preview (#45) * a few more readme tweaks (#46) * Add MIT License to the project (#47) * Add Go (supersedes other PR) (#38) * progress on go * Go translation workflow completed. * missed a few spots * Manual edits * Address feedback * Add gotcha about anonymous local activities * Sample code for payload converter * clarify sdk protection mechanisms * Setup CODEOWNERS to AI SDK team (#48) * Align version number in SKILL.md and plugin.json. (#49) --------- Co-authored-by: James Watkins-Harvey <mjameswh@users.noreply.github.com> Co-authored-by: Chris Olszewski <chrisdolszewski@gmail.com> Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
3.3 KiB
Go Workflow Determinism Protection
Overview
The Go SDK has no runtime sandbox. Determinism is enforced by developer convention and optional static analysis. Unlike the Python and TypeScript SDKs, the Go SDK will not intercept or replace non-deterministic calls at runtime. The Go SDK does perform a limited runtime command-ordering check, but catching non-deterministic code before deployment requires the workflowcheck tool and testing, in particular replay tests (see references/go/testing).
workflowcheck Static Analysis
Install
go install go.temporal.io/sdk/contrib/tools/workflowcheck@latest
Run
workflowcheck ./...
No output means all registered workflows are deterministic. Non-deterministic code produces hierarchical output showing the call chain to the offending code.
Use -show-pos for exact file positions:
workflowcheck -show-pos ./...
What It Detects
Non-deterministic functions/variables:
time.Now-- obtaining current timetime.Sleep-- sleepingcrypto/rand.Reader-- crypto random readermath/rand.globalRand-- global pseudorandomos.Stdin,os.Stdout,os.Stderr-- standard I/O streams
Non-deterministic Go constructs:
- Starting a goroutine (
go func()) - Sending to a channel
- Receiving from a channel
- Iterating over a channel via
range - Iterating over a map via
range
Limitations
workflowcheck cannot catch everything. It does not detect:
- Global variable mutation
- Non-determinism via reflection
- Runtime-conditional non-determinism
Suppressing False Positives
Add //workflowcheck:ignore on or directly above the offending line:
now := time.Now() //workflowcheck:ignore
For broader suppression, use a YAML config file:
# workflowcheck.config.yaml
decls:
path/to/package.MyDeterministicFunc: false
workflowcheck -config workflowcheck.config.yaml ./...
Determinism Rules
You must:
- Use
workflow.Go(ctx, func(ctx workflow.Context) { ... })instead ofgo - Use
workflow.NewChannel(ctx)instead ofchan - Use
workflow.NewSelector(ctx)instead ofselect - Use
workflow.Sleep(ctx, duration)instead oftime.Sleep() - Use
workflow.Now(ctx)instead oftime.Now() - Use
workflow.GetLogger(ctx)instead offmt.Println/log.Println - Sort map keys before iterating, or use
workflow.SideEffect/ an activity
You must not:
- Start native goroutines
- Use native channels or
select - Call
time.Now()ortime.Sleep() - Use
math/randglobal functions orcrypto/rand.Reader - Access
os.Stdin,os.Stdout, oros.Stderr - Mutate global variables
- Make network calls, file I/O, or database queries (use activities)
Best Practices
- Run
workflowcheckin CI / pre-commit -- catch non-deterministic code before it reaches production - Keep workflow code thin -- workflows should orchestrate; delegate all I/O and non-deterministic work to activities
- Use struct methods for activities -- keeps imports clean and avoids pulling non-deterministic dependencies into workflow files
- Separate workflow and activity files -- reduces the surface area that
workflowcheckneeds to analyze and keeps concerns isolated - Test with replay after any workflow code change to verify backward compatibility