Workflow Packages
Install, create, and distribute pre-built workflow packages.
Workflow packages are the standard format for distributing pre-built workflows in Syntropic137.
After running npx syntropic137 setup, installing a workflow package is the fastest way to start
doing useful work with the platform.
Quick Start
# Install the starter research workflow
syn workflow install ./workflows/examples/research-package/
# Run it
syn workflow run research-package-v1 --task "Investigate event sourcing patterns for our platform"
# See what's installed
syn workflow installedInstalling Packages
Workflow packages can be installed from local directories or git repositories:
# Local directory
syn workflow install ./my-package/
# GitHub repository
syn workflow install https://github.com/org/workflow-library
syn workflow install org/workflow-library # Shorthand
syn workflow install org/workflow-library --ref v2.0 # Specific version
# Validate before installing
syn workflow install ./my-package/ --dry-runThe install command resolves all prompt files and shared phases, then creates each
workflow via the API. Installed packages are tracked locally in
~/.syntropic137/workflows/installed.json.
Package Formats
Single Workflow
The simplest format: one workflow with its phase prompts:
Multi-Workflow Plugin
Bundle multiple workflows with a shared phase library:
Shared phases are referenced with the shared:// prefix:
phases:
- id: summarize
prompt_file: shared://summarize # → phase-library/summarize.mdContent is resolved at install time, no runtime dependency on the library.
Creating Packages
Scaffold from Template
# Single workflow
syn workflow init ./my-workflow --name "My Workflow" --type research --phases 3
# Multi-workflow plugin
syn workflow init ./my-plugin --name "My Plugin" --multiPhase Prompt Files
Phase prompts use optional YAML frontmatter followed by the prompt body:
---
model: sonnet
argument-hint: "[topic]"
allowed-tools: Read,Glob,Grep,Bash
max-tokens: 4096
timeout-seconds: 300
---
You are a research assistant investigating: $ARGUMENTS
Use {{discovery}} to reference output from a previous phase.Frontmatter provides defaults; workflow.yaml values always take precedence.
Plugin Manifest
Multi-workflow plugins use syntropic137-plugin.json for metadata:
{
"manifest_version": 1,
"name": "my-plugin",
"version": "1.0.0",
"description": "Research and review workflows",
"author": "my-org",
"license": "MIT"
}Choosing an Agent Harness
Syntropic137 runs phases on two agent harnesses: Claude Code (claude -p) and
OpenAI Codex (codex exec). Selection is per phase, declared in workflow.yaml
under the phase's agent block. There is no CLI flag and no environment variable
for it. A single workflow can mix both.
id: implement-and-review-v1
name: Implement and Review
phases:
- id: implement
name: Implement
order: 1
prompt_file: phases/implement.md
agent:
provider: claude
model: sonnet
allow_delegation: true
- id: review
name: Independent Review
order: 2
prompt_file: phases/review.md
agent:
provider: codex
model: gpt-sol # platform alias for gpt-6-solRunning the same work through two vendors is the main reason to mix them. A codex review phase has no memory of the claude implementation phase beyond the artifacts it is handed, so it is a genuinely independent read of the work.
The agent block
| Field | Values | Default | Notes |
|---|---|---|---|
provider | claude, codex | claude | The harness that drives the phase. The schema rejects any other value. |
model | provider model id or alias | opus (claude), gpt-sol (codex) | Defaults come from SYN_DEFAULT_CLAUDE_MODEL / SYN_DEFAULT_CODEX_MODEL and are recorded at install time. See Codex model ids and cost. |
sandbox | workspace-write, full-access | full-access | Codex phases only. workspace-write is enforced least privilege. See What sandbox actually does. |
allow_delegation | true, false | false | Lets the phase's agent hand work to the other harness. Works in both directions. |
A phase-level model: key, sitting outside the agent block, takes precedence
over agent.model. If you set both, the outer one wins.
What sandbox actually does
sandbox steers codex exec --sandbox. Claude phases ignore it.
| Level | Codex may | Use for |
|---|---|---|
workspace-write | Read, write and run commands inside /workspace, including artifacts/output/ and git commits. Writes outside /workspace are denied. | Any phase that does not need to reach outside the workspace, including review and verify phases. |
full-access (default) | Anything the workspace container allows. | Phases that genuinely need more. |
read-only is refused when you validate, install or execute a workflow. It is
enforced, but it denies the write under artifacts/output/ that every phase
reports through, so the phase could not publish its result.
Codex enforces these levels with bubblewrap, which runs inside a workspace only
because codex-capable workspace images start with a sandbox policy: a narrow
seccomp profile, plus the agentic-codex-sandbox AppArmor profile on AppArmor
hosts (just apparmor-setup). Without it, every level below full-access
fails on its first command.
allowed_tools and the two harnesses
allowed_tools restricts nothing today, on either harness. Treat it as
documentation of intent, not as a control.
Per ADR-069,
_build_agent_config_from_phase builds AgentConfiguration from provider,
model and allow_delegation only. allowed_tools keeps its default of (),
so the guard that would emit --tools never fires and every phase inherits the
full toolset. A closed-vocabulary validator still rejects bash for Bash at
authoring time, which enforces a restriction that is never applied.
The codex path additionally carries an UnsupportedToolPolicyError guard,
because codex exposes no tool flag and translating an allowlist into a sandbox
mode would be a category error. That guard is currently unreachable for the same
reason: allowed_tools never arrives populated.
To bound what a codex phase can write, declare sandbox: workspace-write; see
What sandbox actually does.
Codex authentication
Codex phases need CODEX_AUTH_JSON set on the deployment, holding the full
contents of a Codex ~/.codex/auth.json. Without it, a phase with
agent.provider: codex fails to provision. Claude phases are unaffected.
The agent process itself never receives that environment variable. Provisioning
stages the value to a file, relocates it to ~/.codex/auth.json inside the
workspace at mode 0600, and deletes the staged copy. A codex phase runs with an
empty agent environment, which is also what keeps ANTHROPIC_API_KEY and
CLAUDE_CODE_OAUTH_TOKEN out of reach of a codex run.
For a durable deployment credential that a developer running codex login on a
laptop cannot revoke, use a ChatGPT Business or Enterprise access token. See
Codex access tokens: setup and validation.
Codex model ids and cost
On codex phases, write gpt-sol or a concrete model id such as gpt-6-sol.
gpt-sol is a platform alias: codex has no aliases of its own, so the
platform sends it to codex as --model gpt-6-sol and prices the run as
gpt-6-sol. A codex phase that leaves model unset gets gpt-sol (or whatever
SYN_DEFAULT_CODEX_MODEL names), recorded in the workflow when you install it.
Other codex aliases, such as OpenAI's gpt-5.6, are not translated. Codex may
reject them, and a model the platform has no rate for lands unpriced rather
than wrongly priced.
vendor_cost_usd is always null for codex phases. Token counts are still recorded
for both harnesses.
What each harness gives you
claude | codex | |
|---|---|---|
| Docker workspace isolation | Yes | Yes |
| Tool-call timeline | Yes | Yes, mapped from codex events (command_execution becomes Bash, file_change becomes Edit) |
| Token accounting | Yes | Yes |
Vendor cost (vendor_cost_usd) | Yes | No, always null |
| Delegation to the other harness | Yes | Yes |
| Filesystem sandbox enforcement | No | Yes, workspace-write |
Hook events (PreToolUse, PostToolUse) | Yes | No |
| Subagent tracking | Yes | No |
| TodoWrite and the todo projection | Yes | No |
Claude plugins (--plugin-dir) | Yes | No |
Claude is the richer harness for observability. Codex is the only one that can enforce a filesystem boundary. Pick per phase accordingly: a codex phase will simply produce no hook, subagent, or todo data, and your dashboards for that phase will be correspondingly thinner.
Skills work on both harnesses, because the pinned skills
CLI inside the workspace is harness-neutral.
Exporting Workflows
Export a running workflow from Syntropic137 as a distributable plugin. Exported plugins can be re-imported on another instance or shared via a marketplace.
# Export as a package (workflow.yaml + phase .md files)
syn workflow export <workflow-id> --output ./my-package/
# Export as a plugin (includes CC command wrapper for slash-command invocation)
syn workflow export <workflow-id> --format plugin --output ./my-plugin/Package Format (default)
Produces a directory that can be re-installed with syn workflow install:
Plugin Format
Produces a Syntropic137 plugin with a manifest, CC command wrapper, and workflow:
The commands/syn-*.md wrapper calls syn workflow run, so the exported workflow
can also be invoked as a /syn-* slash command from Claude Code. The package itself
is a Syntropic137 plugin: the CC command is a convenience bridge.
Round-Trip Guarantee
Exported packages are always re-importable:
syn workflow export my-workflow-v1 --output ./exported/
syn workflow install ./exported/ # produces an equivalent workflowValidating Packages
# Validate a package directory
syn workflow validate ./my-package/
# Validate a single YAML file
syn workflow validate ./workflow.yamlValidation checks the YAML schema, verifies that all referenced .md files exist,
and resolves shared:// references.
Retired phase fields
A phase field that no longer does anything is retired rather than refused, so
workflows written before the change keep loading. validate and install
print a warning naming the phase and the field; the workflow is still valid and
the value is ignored. Any other unknown field is still an error.
| Field | Retired | Why | What to do |
|---|---|---|---|
can_open_pr | after #1477 | Every phase's token carries the installation's own permissions, so every phase may open and comment on a PR. The field decided nothing. | Delete the line. There is no replacement. |
Warning: phase 'open_pr': 'can_open_pr' is retired (#1477) and ignored - ...A future release will refuse retired fields at validate and install time, so remove them now.
Example Packages
The repository includes reference implementations:
workflows/examples/research-package/: Single workflow with discovery + synthesis phasesworkflows/examples/starter-plugin/: Multi-workflow plugin with shared summarize phase
Marketplace
The marketplace lets you discover, install, and share workflow plugins from
GitHub-hosted registries. Any GitHub repository with a marketplace.json at the
root can serve as a marketplace.
Register a Marketplace
# Add the official Syntropic137 marketplace
syn marketplace add syntropic137/workflow-library
# Add a company-internal marketplace
syn marketplace add myorg/internal-workflows --name my-company
# Add from a specific branch or tag
syn marketplace add myorg/workflows --ref v2.0
# List registered marketplaces
syn marketplace list
# Refresh cached indexes
syn marketplace refresh
# Refresh a specific marketplace
syn marketplace refresh my-company
# Remove a marketplace
syn marketplace remove my-companyDiscover Workflows
# Search across all registered marketplaces
syn workflow search "research"
syn workflow search --category research
syn workflow search --tag multi-phase
# Show details of a specific plugin
syn workflow info research-toolkitSearch matches against plugin name, description, category, and tags (case-insensitive). An empty query returns all plugins across all registries.
Install from Marketplace
# Install by plugin name (resolved from registered marketplaces)
syn workflow install research-toolkit
# Still works: install from local paths and git URLs
syn workflow install ./my-package/
syn workflow install org/repoWhen you pass a bare name (no slashes, not a path), the CLI checks registered marketplaces first. If found, it clones the marketplace repo, resolves the plugin's subdirectory, and installs the workflows.
Update and Uninstall
# Update a package to the latest version
syn workflow update research-toolkit
# Check for updates without applying
syn workflow update research-toolkit --dry-run
# Uninstall (removes workflows from the platform)
syn workflow uninstall research-toolkit
# Uninstall but keep workflows running
syn workflow uninstall research-toolkit --keep-workflowsUpdates compare the remote git SHA against the installed SHA. If they match, the package is already up to date and no action is taken.
Creating a Marketplace Repository
Any GitHub repository can be a marketplace. Create a marketplace.json at the
root and organize plugins in subdirectories:
Step 1: Create the Repository Structure
Step 2: Write marketplace.json
{
"name": "my-marketplace",
"syntropic137": {
"type": "workflow-marketplace"
},
"plugins": [
{
"name": "research-toolkit",
"source": "./plugins/research-toolkit",
"version": "1.2.0",
"description": "Deep research and quick-scan workflows",
"category": "research",
"tags": ["multi-phase", "deep-dive", "synthesis"]
},
{
"name": "pr-automation",
"source": "./plugins/pr-automation",
"version": "0.5.0",
"description": "Automated PR review and feedback",
"category": "ci",
"tags": ["github", "code-review"]
}
]
}Step 3: Push and Register
git push origin main
# Users register your marketplace:
syn marketplace add your-org/my-marketplacemarketplace.json Schema
The marketplace.json file is the index that describes all plugins in the
marketplace. It must be a JSON object at the repository root.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Human-readable marketplace name (used as default registry name) |
syntropic137 | object | Yes | Marker identifying this as a Syntropic137 marketplace |
syntropic137.type | string | Yes | Must be "workflow-marketplace" |
syntropic137.min_platform_version | string | No | Minimum platform version (default "0.0.0") |
plugins | array | No | List of plugin entries (default []) |
Each plugin entry in the plugins array:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique plugin name (used for syn workflow install <name>) |
source | string | Yes | Relative path to the plugin directory (e.g., "./plugins/my-plugin") |
version | string | No | Semver version string (default "0.1.0") |
description | string | No | Short description shown in search results |
category | string | No | Plugin category (e.g., "research", "ci", "analysis") |
tags | array | No | List of tags for filtering (e.g., ["multi-phase", "github"]) |
The source path must be relative (no absolute paths or .. traversal). Each
plugin directory follows the standard package format: either
a single workflow or a multi-workflow plugin.
Caching and Refresh
Marketplace indexes are cached locally at ~/.syntropic137/marketplace/cache/
to avoid cloning on every search or install.
- Cache TTL: 4 hours. After this, the next search or install re-fetches the index.
- Force refresh:
syn marketplace refreshbypasses the TTL and fetches fresh indexes. - Cache location:
~/.syntropic137/marketplace/cache/<registry-name>.json - Registry config:
~/.syntropic137/registries.json
Searches and plugin lookups use the cache when fresh, falling back to a fresh fetch when stale. If a fetch fails (network error, repo not found), stale cache entries are skipped silently.
Private Marketplaces
Private GitHub repositories work as marketplaces if git can authenticate. The CLI uses your local git credential configuration, no special flags needed.
# Ensure git can access the private repo (any of these work):
# - GitHub CLI: gh auth login
# - SSH key: git clone git@github.com:myorg/private-marketplace.git
# - Credential helper: git config credential.helper
# Then register normally:
syn marketplace add myorg/private-marketplace --name internalFor CI environments, set the GIT_ASKPASS or GH_TOKEN environment variable,
or configure a credential helper that reads from environment variables.
Troubleshooting
"No marketplace.json found in repo": The repository must have a
marketplace.json at the root of the default branch (or the branch specified
with --ref).
"syntropic137.type must be 'workflow-marketplace'": The syntropic137
key in marketplace.json must contain "type": "workflow-marketplace".
This marker distinguishes marketplace repos from other Syntropic137 content.
"Invalid registry name": Registry names must start with an alphanumeric
character and contain only letters, digits, hyphens, underscores, and dots.
Names like ../evil or my/registry are rejected.
Plugin not found after registering: Run syn marketplace refresh to
re-fetch the latest index. The local cache may be stale.
Private repo access denied: Ensure git clone works for the repo URL
from your terminal. The CLI uses the same git credentials as your shell.
"Package is already up to date": syn workflow update compares git
SHAs. If the remote HEAD hasn't changed, no update is needed.
Limitations
- One marketplace index per repository (no nested marketplace files)
- No dependency resolution between plugins
- No version conflict detection across multiple marketplaces
- No rollback to a previous plugin version (uninstall and re-install at a pinned
--ref) - Search is substring-based, not fuzzy or ranked
Phase Outcomes and Artifacts
Every phase ends with a TASK_RESULT block reporting success, and, where
they apply, failure_reason and side_effects. The platform weighs that
report against the run's exit status to decide whether the phase completed.
Every phase must also leave an artifact: whatever it writes under
artifacts/output/ is collected, and a phase that wrote nothing has its last
message recovered as a marked artifact, or fails if that message says nothing
usable. See How a Phase Reports Its Outcome.
Learn More
- CLI Reference: all
syn workflowandsyn marketplacecommands - API Reference: workflow creation endpoints
Syntropic137 Docs v0.33.1 · Last updated March 2026