Creating Custom Scaffolds
This guide covers two related workflows: modifying a scaffold to meet custom requirements (Lifecycle C) and extracting a new scaffold from a working tentacle (Lifecycle D).
Part 1: Modifying a Scaffold (Lifecycle C)
Section titled “Part 1: Modifying a Scaffold (Lifecycle C)”Use this path when a scaffold is close to what you need but requires structural changes — different config layout, additional nodes, modified data flow, or different contract dependencies.
When to Modify vs. Use As-Is
Section titled “When to Modify vs. Use As-Is”| Situation | Path |
|---|---|
| Need to change config values only (URLs, schedules, thresholds) | Lifecycle B — use as-is |
| Need to add/remove nodes or change the DAG structure | Lifecycle C — modify |
| Need to restructure the config section (e.g., flat list to grouped regions) | Lifecycle C — modify |
| Need different contract dependencies | Lifecycle C — modify |
1. Initialize from the Scaffold
Section titled “1. Initialize from the Scaffold”tntc scaffold init uptime-tracker regional-uptime --no-params2. Plan Your Changes
Section titled “2. Plan Your Changes”Before editing, review the scaffold’s workflow.yaml and node code. Identify:
- What to keep (reusable logic, patterns)
- What to change (config structure, nodes, contract)
- What to add (new nodes, new dependencies)
3. Make Structural Changes
Section titled “3. Make Structural Changes”Edit workflow.yaml freely. For example, restructuring a flat endpoint list into regional groups:
config: timeout: 120s retries: 1 regions: - name: us latency_threshold_ms: 1500 slack_channel: "#us-ops" endpoints: - url: "https://us.acme.com" expected_body: "" - name: eu latency_threshold_ms: 2000 slack_channel: "#eu-ops" endpoints: - url: "https://eu.acme.com" expected_body: ""Modify node code as needed. Add or remove nodes. Update edges.
4. Update Metadata
Section titled “4. Update Metadata”Delete or rewrite params.schema.yaml:
- Delete if the structure diverged significantly from the original scaffold
- Rewrite if you plan to extract this tentacle as a new scaffold later
Update tentacle.yaml to reflect the modification:
name: regional-uptimecreated: 2026-03-22T14:30:00Zscaffold: name: uptime-tracker version: "1.0" source: public modified: true5. Validate and Deploy
Section titled “5. Validate and Deploy”tntc validatetntc testtntc deployPart 2: Extracting a Scaffold (Lifecycle D)
Section titled “Part 2: Extracting a Scaffold (Lifecycle D)”After building a working tentacle — whether from scratch or by modifying a scaffold — you can extract it as a reusable scaffold. This is how the scaffold library grows organically.
When to Extract
Section titled “When to Extract”- The tentacle solves a pattern that other projects could reuse
- You want to share an org-specific pattern across your team
- You want to contribute a public quickstart
1. Analyze the Tentacle
Section titled “1. Analyze the Tentacle”Run extraction analysis from within the tentacle directory:
cd ~/tentacles/regional-uptimetntc scaffold extract --jsonThis outputs a JSON analysis identifying:
- Values that appear org-specific (URLs, channel names, org names) — these will be parameterized
- Values that are structural defaults (timeouts, retry counts) — these may become parameters with defaults
- Node code and contract structure — copied as-is
2. Review the Parameterization Plan
Section titled “2. Review the Parameterization Plan”The extraction heuristics classify values into three categories:
Parameterize (replace with safe examples):
- Custom domain URLs, organization names, Slack channels, GitHub repos, email addresses
Parameterize with current value as default:
- Numeric thresholds, cron schedules, batch sizes
Do NOT parameterize:
- Well-known API hosts (
api.anthropic.com), exoskeleton dependency names and protocols, node graph structure
3. Generate Scaffold Files
Section titled “3. Generate Scaffold Files”# Save as a private scaffold (default)tntc scaffold extract --name regional-uptime-tracker
# Or save for public contributiontntc scaffold extract --name regional-uptime-tracker --publicPrivate scaffolds are saved to ~/.tentacular/scaffolds/<name>/. Public scaffolds are saved to ./scaffold-output/ for review before PR.
4. Review Generated Files
Section titled “4. Review Generated Files”The extraction generates:
scaffold-output/+-- scaffold.yaml # Metadata+-- workflow.yaml # Real values replaced with safe examples+-- params.schema.yaml # Parameter declarations+-- params.yaml.example # Example parameter values+-- .secrets.yaml.example # Sanitized secret structure+-- nodes/ # Node code (copied as-is)+-- tests/fixtures/ # Test fixtures (copied as-is)+-- README.md # Generated documentationReview workflow.yaml to verify org-specific values were properly replaced. Review params.schema.yaml to verify parameter descriptions are clear.
5. Publish (Optional)
Section titled “5. Publish (Optional)”For private scaffolds, you are done. The scaffold is immediately available via tntc scaffold list --source private.
For public quickstarts, submit a PR to the tentacular-scaffolds repo with the contents of ./scaffold-output/.
Authoring params.schema.yaml
Section titled “Authoring params.schema.yaml”When writing or editing params.schema.yaml manually:
Parameter Definition
Section titled “Parameter Definition”version: "1"description: "Parameters for the regional-uptime-tracker scaffold"
parameters: regions: path: config.regions type: list items: map description: > Region definitions for uptime monitoring. Each region has a name, latency threshold in ms, Slack channel for alerts, and a list of HTTP endpoints to probe. required: true example: - name: "us-east" latency_threshold_ms: 2000 slack_channel: "#us-east-ops" endpoints: - url: "https://example.com" expected_body: ""Path Expression Syntax
Section titled “Path Expression Syntax”The path field uses a minimal syntax to point into workflow.yaml:
| Pattern | Example | Meaning |
|---|---|---|
| Dot-separated keys | config.endpoints | Navigate nested mappings |
| Filtered key | triggers[name=check-endpoints].schedule | Find list element by field value |
Type System
Section titled “Type System”| Type | YAML Representation |
|---|---|
string | Scalar |
number | Integer or float |
boolean | true / false |
list | Sequence (use items for element type) |
map | Mapping |
Guidelines
Section titled “Guidelines”- Write descriptions for a machine that relays to a human — be concise and unambiguous
- Use realistic but not real example values (
https://example.com/pricingoverhttps://example.com) - Mark parameters
required: trueonly when there is no sensible default - Set
defaultfor optional parameters with reasonable starting values - Secrets are never parameters — they use
.secrets.yaml, notparams.schema.yaml
Next Steps
Section titled “Next Steps”- Getting Started from a Scaffold — The simpler Lifecycle B path
- Scaffold Usage — Browse and search all available scaffolds
- Workspace Layout — Understand the directory structure