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 installed

Installing 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-run

The 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:

workflow.yaml
discover.md
synthesize.md
README.md

Multi-Workflow Plugin

Bundle multiple workflows with a shared phase library:

syntropic137-plugin.json
workflow.yaml
workflow.yaml
summarize.md
README.md

Shared phases are referenced with the shared:// prefix:

phases:
  - id: summarize
    prompt_file: shared://summarize  # → phase-library/summarize.md

Content 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" --multi

Phase 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.

workflow.yaml
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-sol

Running 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

FieldValuesDefaultNotes
providerclaude, codexclaudeThe harness that drives the phase. The schema rejects any other value.
modelprovider model id or aliasopus (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.
sandboxworkspace-write, full-accessfull-accessCodex phases only. workspace-write is enforced least privilege. See What sandbox actually does.
allow_delegationtrue, falsefalseLets 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.

LevelCodex mayUse for
workspace-writeRead, 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

claudecodex
Docker workspace isolationYesYes
Tool-call timelineYesYes, mapped from codex events (command_execution becomes Bash, file_change becomes Edit)
Token accountingYesYes
Vendor cost (vendor_cost_usd)YesNo, always null
Delegation to the other harnessYesYes
Filesystem sandbox enforcementNoYes, workspace-write
Hook events (PreToolUse, PostToolUse)YesNo
Subagent trackingYesNo
TodoWrite and the todo projectionYesNo
Claude plugins (--plugin-dir)YesNo

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:

workflow.yaml
discovery.md
synthesis.md
README.md

Plugin Format

Produces a Syntropic137 plugin with a manifest, CC command wrapper, and workflow:

syntropic137-plugin.json
syn-deep-research.md
workflow.yaml
discovery.md
synthesis.md
README.md

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 workflow

Validating Packages

# Validate a package directory
syn workflow validate ./my-package/

# Validate a single YAML file
syn workflow validate ./workflow.yaml

Validation 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.

FieldRetiredWhyWhat to do
can_open_prafter #1477Every 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 phases
  • workflows/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-company

Discover 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-toolkit

Search 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/repo

When 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-workflows

Updates 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

marketplace.json
syntropic137-plugin.json
README.md

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-marketplace

marketplace.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.

FieldTypeRequiredDescription
namestringYesHuman-readable marketplace name (used as default registry name)
syntropic137objectYesMarker identifying this as a Syntropic137 marketplace
syntropic137.typestringYesMust be "workflow-marketplace"
syntropic137.min_platform_versionstringNoMinimum platform version (default "0.0.0")
pluginsarrayNoList of plugin entries (default [])

Each plugin entry in the plugins array:

FieldTypeRequiredDescription
namestringYesUnique plugin name (used for syn workflow install <name>)
sourcestringYesRelative path to the plugin directory (e.g., "./plugins/my-plugin")
versionstringNoSemver version string (default "0.1.0")
descriptionstringNoShort description shown in search results
categorystringNoPlugin category (e.g., "research", "ci", "analysis")
tagsarrayNoList 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 refresh bypasses 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 internal

For 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

Syntropic137 Docs v0.33.1 · Last updated March 2026

On this page