Large engineering problems rarely arrive with clear boundaries. When building something new—especially integrating with unfamiliar systems—you often don’t know what you don’t know.
This guide demonstrates how to use sudocode’s hierarchical spec system to progressively decompose ambiguous problems into smaller specifications.The pattern:
Start by discussing your problem statement and design constraints with the agent
Use the agent to conduct initial research and planning, and create a spec that captures the overall plan
Discuss the spec with your agent to surface unknowns
Identify areas of ambiguity through Q&A
Carve out a sub-specification for scoped investigation of ambiguities
Design experiments to validate assumptions
Link discoveries back to original spec, using sub-spec as documentation for disambiguations and implementations
We’ll walk through building a wrapper API for coder-server, an open-source VS Code in the browser. Specifically, we need to understand how authentication flows work—both OpenID Connect sharing and GitHub authentication—across our wrapper API and the underlying coder server.This is a perfect case for spec breakdown because:
The integration surface is unclear
Authentication flows span multiple systems
We need to discover how the existing system works before designing our wrapper
Before creating any artifacts, start with a conversation to understand the problem space. The agent conducts research and presents learnings to the user.Step 1: Discuss the problem and constraintsVia the sudocode web server at localhost:3000/executions, or in your agent CLI (with the sudocode MCP enabled), start a conversation with the agent to discuss your problem and constraints.
Copy
> User: I want to build a wrapper API around coder-server. We need to create users, start workspaces on their behalf, and run our own code on top. What do we need to figure out?⏺ Agent: Let me explore coder-server to understand its API surface.⏺ Read(coder-server docs, API reference) ⎿ Analyzing capabilities...⏺ Agent: Coder-server exposes APIs for: - User management (create, list, permissions) - Workspace lifecycle (create, start, stop, delete) - Template management for workspace configurations Key questions for our wrapper: 1. How do we want to model users? Mirror coder-server or our own? 2. What workspace operations do we need to expose? 3. How will authentication work between our API and coder-server?> User: We have our own user model. We want to map our users to coder-server users and manage workspaces through our API.⏺ Agent: Got it. Should I create a spec capturing the wrapper API design with these requirements?
Step 2: Agent creates the initial spec
Copy
> User: Yes, let's create a spec.⏺ plugin:sudocode:sudocode - upsert_spec (MCP) (title: "Coder Server Wrapper API", description: "# Coder Server Wrapper API## OverviewBuild a wrapper API around coder-server that integrates with ourplatform's user model and exposes workspace management.## API Surface### User Management- Map platform users to coder-server users- Sync user creation/deletion- Handle permissions mapping### Workspace Operations- Create workspace for user- Start/stop workspace- Delete workspace- Get workspace status## Open Questions- How do we authenticate requests to coder-server on behalf of users?- Should we use coder-server's native auth or proxy through our API?- How do we handle session lifecycle across both systems?## ArchitectureTBD - pending auth investigation") ⎿ { "id": "s-8k2m", ... }
The spec captures the API surface and explicitly lists Open Questions—unknowns are first-class content.Review the spec in the web UI at localhost:3000. Navigate to the Specs page to see the rendered markdown, review the structure, and make any edits before continuing.
With a spec in place, discuss it to probe deeper. The goal is to identify which unknowns are blocking and need focused investigation.Step 3: Discuss the spec to surface unknowns
Copy
> User: Let's talk through this spec. The auth question seems like the biggest unknown. How can our server share authentication with coder-server?⏺ Agent: That's the key architectural question. Let me research coder-server's auth options...⏺ Read(coder-server auth docs) ⎿ ...⏺ Agent: Coder-server supports several auth modes: - OIDC with external providers - Proxy authentication (trust headers from reverse proxy) - Native GitHub OAuth For sharing auth, two approaches seem viable: **OIDC Token Sharing** - Both systems use same OIDC provider **Proxy Auth** - Our API proxies requests with trusted headers Each has unknowns we'd need to investigate before committing.
Step 4: Identify specific ambiguities to investigate
Copy
> User: What are the critical unknowns for each approach?⏺ Agent: **OIDC**: Can coder-server accept tokens issued by our provider? If not, this approach won't work. **Proxy Auth**: How do we secure the trust boundary? If we can't prevent header spoofing, it's too risky. I'd recommend carving out sub-specs to investigate each approach before committing to an architecture.> User: Let's focus on OIDC first—seems cleaner if it works.
This discussion identified two competing architectural approaches that need investigation before we can proceed.
Here’s where hierarchical specs shine. Instead of trying to resolve ambiguity in the parent spec, you carve out focused sub-specs to investigate specific unknowns. Each sub-spec isolates one area of ambiguity for deep investigation.Step 5: Carve out an investigation sub-spec
Copy
> User: Let's carve out a sub-spec to investigate the OIDC token sharing approach. I want to understand if this is actually feasible before we commit to it.⏺ Agent: I'll create a focused sub-spec for the OIDC investigation.⏺ plugin:sudocode:sudocode - upsert_spec (MCP) (title: "OIDC Token Sharing Investigation", parent: "s-8k2m", description: "# OIDC Token Sharing Investigation## Parent Spec[[s-8k2m]] - Coder Server Authentication Wrapper API## ObjectiveDetermine if OIDC token sharing between our platform and coder-serveris feasible and practical.## Questions to Answer1. Can coder-server accept tokens issued by our OIDC provider?2. What OIDC claims does coder-server require?3. How does coder-server handle token validation and refresh?4. Can we configure both systems to use the same OIDC client?## Experiments### Experiment 1: OIDC Configuration Analysis**Goal:** Document coder-server's OIDC configuration requirements**Method:**- Review coder-server OIDC documentation- Examine environment variables and config options- Compare with our GitHub OIDC setup**Success Criteria:** Clear mapping of required vs optional OIDC params### Experiment 2: Token Acceptance Test**Goal:** Verify coder-server accepts our platform's tokens**Method:**- Configure test coder-server with our OIDC provider- Attempt authentication with platform-issued token- Document any token transformation needed**Success Criteria:** Successful auth with shared token### Experiment 3: Session Lifecycle Test**Goal:** Understand how token expiry affects both systems**Method:**- Authenticate to both systems with shared token- Let token expire- Document behavior in each system**Success Criteria:** Clear understanding of refresh requirements## Findings(To be filled in after experiments)## Recommendation(To be filled in after experiments)") ⎿ { "id": "s-9p3q", ... }
Create sub-specs for alternative approaches too:
Copy
> User: Now create a similar sub-spec for the proxy auth approach.⏺ plugin:sudocode:sudocode - upsert_spec (MCP) (title: "Proxy Authentication Investigation", parent: "s-8k2m", description: "# Proxy Authentication Investigation## Parent Spec[[s-8k2m]] - Coder Server Authentication Wrapper API## ObjectiveDetermine if proxy authentication is a viable approach forintegrating coder-server with our platform.## Questions to Answer1. What headers does coder-server trust for proxy auth?2. How do we secure the proxy trust boundary?3. How should we handle session lifecycle independently?4. What user attributes can we pass via proxy headers?## Experiments### Experiment 1: Proxy Auth Configuration**Goal:** Document coder-server's proxy auth setup**Method:**- Review proxy auth documentation- Identify required headers and configuration- Test with simple nginx proxy**Success Criteria:** Working proxy auth in isolated test### Experiment 2: Security Boundary Analysis**Goal:** Understand trust model and potential vulnerabilities**Method:**- Document how coder-server validates proxy headers- Identify spoofing risks- Design mitigation strategies**Success Criteria:** Security model documented with mitigations### Experiment 3: Session Management Design**Goal:** Design independent session lifecycle management**Method:**- Map our session lifecycle to coder-server sessions- Design session creation/destruction hooks- Handle edge cases (timeout, logout, etc.)**Success Criteria:** Complete session management design## Findings(To be filled in after experiments)## Recommendation(To be filled in after experiments)") ⎿ { "id": "s-7r4t", ... }
Now we have a clear structure:
Copy
s-8k2m: Coder Server Authentication Wrapper API (parent)├── s-9p3q: OIDC Token Sharing Investigation (child)└── s-7r4t: Proxy Authentication Investigation (child)
With sub-specs carved out, design concrete experiments to validate assumptions. Each experiment should have a clear goal, method, and success criteria. Execute experiments as issues linked to the sub-spec.Step 6: Execute experiments as issues
Copy
> User: Let's create issues for the OIDC investigation experiments. Start with experiment 1.⏺ plugin:sudocode:sudocode - upsert_issue (MCP) (title: "Analyze coder-server OIDC configuration requirements", description: "## ObjectiveDocument coder-server's OIDC configuration and compare with our setup.## Implements[[s-9p3q]] - OIDC Token Sharing Investigation (Experiment 1)## Tasks- [ ] Review coder-server OIDC documentation- [ ] List all OIDC environment variables- [ ] Document required vs optional claims- [ ] Compare with our GitHub OIDC configuration- [ ] Identify gaps or incompatibilities## DeliverableConfiguration comparison document added to spec findings.", status: "open") ⎿ { "id": "i-5kw2", ... }⏺ plugin:sudocode:sudocode - link (MCP) (from_id: "i-5kw2", to_id: "s-9p3q", type: "implements")
Capture findings as feedback on the sub-spec:
Copy
⏺ Agent: [Executes experiment, researches coder-server OIDC]⏺ plugin:sudocode:sudocode - add_feedback (MCP) (to_id: "s-9p3q", issue_id: "i-5kw2", content: "## Experiment 1 Findings### OIDC Configuration RequirementsCoder-server requires these OIDC settings:- `CODER_OIDC_ISSUER_URL` - Must match our provider- `CODER_OIDC_CLIENT_ID` - Can share with our app- `CODER_OIDC_CLIENT_SECRET` - Can share with our app- `CODER_OIDC_EMAIL_DOMAIN` - Optional, for domain restriction### Comparison with Our Setup| Parameter | Our Platform | Coder-Server | Compatible? ||-----------|--------------|--------------|-------------|| Issuer | GitHub | GitHub | ✅ Yes || Client ID | abc123 | (configurable) | ✅ Yes || Scopes | openid,email | openid,profile,email | ⚠️ Need profile |### Gap IdentifiedCoder-server requires the `profile` scope which we don't currentlyrequest. This is a minor change to our OIDC configuration.### RecommendationOIDC sharing appears feasible with minor scope adjustment.", type: "comment", text: "## Findings")
After experiments complete, link discoveries back to the original spec. The sub-spec becomes permanent documentation of what was investigated and decided. Update the parent spec with the architectural decision.Step 7: Update sub-spec with findings and link back to parent
Copy
⏺ plugin:sudocode:sudocode - upsert_spec (MCP) (spec_id: "s-9p3q", description: "...existing content...## Findings### Experiment 1: OIDC Configuration ✅OIDC sharing is feasible. Requires adding `profile` scope to ourGitHub OAuth configuration. See feedback from [[i-5kw2]].### Experiment 2: Token Acceptance ✅Coder-server successfully accepts tokens from our OIDC providerwhen configured with shared client credentials.### Experiment 3: Session Lifecycle ⚠️Token refresh works, but coder-server maintains its own sessionthat can outlive our token. Need session termination hook.## Recommendation**OIDC token sharing is viable** with these requirements:1. Add `profile` scope to our OAuth config2. Share OIDC client credentials with coder-server3. Implement session termination webhook for logout sync")
Update parent spec with the architectural decision:
Copy
> User: Based on the OIDC investigation, let's update the parent spec with our chosen approach.⏺ plugin:sudocode:sudocode - upsert_spec (MCP) (spec_id: "s-8k2m", description: "# Coder Server Authentication Wrapper API## OverviewBuild a wrapper API that provides seamless authentication between ourplatform (GitHub OAuth) and coder-server instances.## Architectural Decision**Approach: OIDC Token Sharing** (decided after investigation)Based on [[s-9p3q]], OIDC token sharing is the recommended approach:- Minimal configuration changes required- True SSO experience for users- Token lifecycle naturally synchronizedSee [[s-7r4t]] for proxy auth analysis (not chosen).## Architecture
Don’t pretend you know more than you do. “Open Questions” and “TBD” sections are valuable—they make unknowns visible and trackable.
Design experiments with clear success criteria
Each experiment should have:
A specific question it answers
A concrete method to execute
Clear criteria for what “success” looks like
Keep sub-specs focused
Each sub-spec should investigate one area of ambiguity. If you find yourself with compound questions, split into multiple sub-specs.
Link everything bidirectionally
Use [[id]] references liberally. The parent should reference children, children should reference parents, and issues should reference the specs they implement.
Archive rather than delete
When you choose one approach over another, archive the unchosen sub-spec rather than deleting it. It documents the decision rationale.