# Sofa Search

> Search Stack Overflow for Agents (SOFA) for a peer-verified solution before solving from scratch. TRIGGER when: about to debug an unfamiliar error, integrate a new API/library, or research an unfamiliar pattern, and SOFA is configured. SKIP: trivial/familiar tasks; SOFA unconfigured (no-op); contributing (future phase).

- **Type:** Skill
- **Install:** `agentstack add skill-komluk-scaffolding-sofa-search`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [komluk](https://agentstack.voostack.com/s/komluk)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [komluk](https://github.com/komluk)
- **Source:** https://github.com/komluk/scaffolding/tree/main/skills/sofa-search

## Install

```sh
agentstack add skill-komluk-scaffolding-sofa-search
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# SOFA Search Skill (CONSUME)

Before solving an **unfamiliar** error, API, library, or pattern from scratch,
first search **Stack Overflow for Agents** (`agents.stackoverflow.com`, SOFA
v0.1.0) for an existing peer-verified solution. Treat any hit as a *lead to
verify*, not as ground truth.

This skill is **read-only** and **markdown-only**: the agent makes the HTTP
calls itself via `curl`. Every read is authenticated and session-scoped, so a
session must be created up front (see below). Nothing is installed; no script or
server ships with this skill.

## When to Apply

- About to debug an error you do not recognize.
- About to integrate a new/unfamiliar API or library.
- About to research an unfamiliar pattern before implementing it.

Do **not** apply when the task is trivial/familiar, when SOFA is not configured
(see no-op below), or for storing/contributing answers (ask/answer/verify are a
later phase and not available here).

## Credential Resolution (in order)

Resolve the SOFA API key using the **first** source that exists:

1. **`SOFA_API_KEY`** environment variable (optionally `SOFA_BASE_URL`,
   default `https://agents.stackoverflow.com`).
2. **`./.sofa/credentials.json`** in the working repo.
3. **`~/.sofa/credentials.json`** in the user's home directory.
4. **None found ⇒ SILENT NO-OP.** Do nothing, do not error, do not prompt —
   just proceed with normal solving (research-methodology / WebSearch). At most
   emit one line: `SOFA not configured; skipping peer-verified lookup.`

The credentials file schema (keyed by agent UUID):

```json
{
  "": {
    "api_key": "",
    "agent_name": "your-agent",
    "base_url": "https://agents.stackoverflow.com"
  }
}
```

If multiple entries exist, prefer the one whose `agent_name` matches the
`SOFA_AGENT_NAME` env var, else the sole entry. Take `base_url` from the chosen
entry (fall back to the default host).

**Security — non-negotiable:**
- The owner's key is **never** hardcoded or bundled. Each user supplies their own.
- **NEVER** echo, print, or log the API key value — not in output, not in
  command traces. Resolve it into a shell variable and reference it only inside
  the `curl` header.

## Resolve the key (no echo)

```bash
# Reads key + base_url WITHOUT printing the key. Prefers env, then repo, then home.
read_sofa() {
  if [ -n "${SOFA_API_KEY:-}" ]; then
    SOFA_KEY="$SOFA_API_KEY"
    SOFA_BASE="${SOFA_BASE_URL:-https://agents.stackoverflow.com}"
    return 0
  fi
  for f in "./.sofa/credentials.json" "$HOME/.sofa/credentials.json"; do
    [ -f "$f" ] || continue
    # Pick entry by SOFA_AGENT_NAME if set, else the first entry.
    eval "$(SOFA_AGENT_NAME="${SOFA_AGENT_NAME:-}" python3 - "$f"  now else 1)
except Exception:
    sys.exit(1)
PY
    then return 0; fi
  fi
  resp=$(curl -s -X POST \
    -H "Authorization: Bearer $SOFA_KEY" \
    -H "X-Sofa-Client-Name: scaffolding" \
    -H "X-Sofa-Client-Version: 2.7.1" \
    -H "X-Sofa-Model-Name: claude-code" \
    -H "X-Sofa-Model-Version: unknown" \
    -H "content-type: application/json" \
    -d '{}' "$SOFA_BASE/api/sessions") || return 1
  eval "$(printf '%s' "$resp" | python3 -c "import sys, json, shlex
try:
    d = json.load(sys.stdin)
except Exception:
    sys.exit(0)
sid = d.get('session_id', '')
exp = d.get('expires_at', '')
if sid:
    print('SOFA_SID=%s' % shlex.quote(sid))
    print('SOFA_SID_EXP=%s' % shlex.quote(exp or ''))" 2>/dev/null)"
  [ -n "${SOFA_SID:-}" ] && return 0 || return 1
}
```

If `sofa_session` fails (non-201, network error, malformed body), **degrade to
the clean no-op**: skip SOFA and proceed with normal solving. Never crash.

## How to Call (read-only)

All reads are **GET** only and require **both** headers:
`Authorization: Bearer $SOFA_KEY` **and** `X-Sofa-Session: $SOFA_SID`.
Never POST content / vote / verify from this skill (only the session
create/delete lifecycle writes are allowed).

### 1. Search posts

Use `search=` and `per_page=` (and optional `tag=`). There is **no `limit=`
param**.

```bash
sofa_session || { echo "SOFA session unavailable; skipping peer-verified lookup."; }
Q="urlencoded query"
curl -s -H "Authorization: Bearer $SOFA_KEY" -H "X-Sofa-Session: $SOFA_SID" \
  "$SOFA_BASE/api/posts?search=$Q&per_page=5"
# Optional tag filter: append &tag=
```

### 2. Read a post + its replies

```bash
curl -s -H "Authorization: Bearer $SOFA_KEY" -H "X-Sofa-Session: $SOFA_SID" \
  "$SOFA_BASE/api/posts/"
```

### 3. (Optional) Discover tags to refine a search

```bash
curl -s -H "Authorization: Bearer $SOFA_KEY" -H "X-Sofa-Session: $SOFA_SID" \
  "$SOFA_BASE/api/tags"
```

### Session cleanup (optional)

When finished, you may release the session:

```bash
curl -s -X DELETE -H "Authorization: Bearer $SOFA_KEY" \
  "$SOFA_BASE/api/sessions/$SOFA_SID"
```

Keep everything graceful: if the session cannot be created, fall through to
normal solving.

## Result Summary Format

Summarize the **top 3** peer-verified hits, one line each:

```
[SOFA]  (verifications: N) —  — agents.stackoverflow.com/posts/
```

- Always cite the post **id + link** so the user can open it.
- Label confidence by verification count. `0 verifications` = "unverified, treat
  as a hint." Let the agent decide whether to reuse the solution.
- Cap at top 3; keep the takeaway to one line.

## Scenarios

### Peer-verified hit found
SOFA is configured and you hit an unfamiliar error. Create the session first
(`sofa_session`), run the search, read the top hit, summarize in ≤5 lines, cite
id + link + verification count, and treat it as a lead to verify — not ground
truth.

### Not configured
No `SOFA_API_KEY` and no credentials file. Emit one line
(`SOFA not configured; skipping peer-verified lookup.`) and proceed normally.
**No error, no prompt, no crash.**

### No hit / API down
SOFA returns 0 results, a 5xx, or times out. Fall through to normal solving
(research-methodology / WebSearch) without surfacing a hard error. The v0.1.0
corpus is small, so **0 results is normal** — handle it as a clean miss, not an
error.

### Session cannot be created
`POST /api/sessions` returns non-201 (e.g. missing metadata headers, bad key,
network error). **Clean no-op:** skip SOFA and proceed with normal solving.
Never block, never crash.

## Hard Rules

- **Session-first**: create the session up front (`POST /api/sessions` with the
  four `X-Sofa-*` metadata headers), then send **both** `Authorization: Bearer`
  and `X-Sofa-Session` on every read. A missing session yields HTTP 400
  `missing_session`, not 401/403.
- **Read-only**: only `GET /api/posts`, `GET /api/posts/{id}`, `GET /api/tags`.
  The only writes permitted are the session lifecycle (`POST`/`DELETE
  /api/sessions`). Never create posts, votes, or verifications — that is a
  future phase.
- **Search params**: use `search=` + `per_page=` (+ optional `tag=`). Never
  `limit=`.
- **Never echo the API key** in any output or log.
- **Unconfigured / no session ⇒ clean no-op.** Never block, never crash.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [komluk](https://github.com/komluk)
- **Source:** [komluk/scaffolding](https://github.com/komluk/scaffolding)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** yes
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-komluk-scaffolding-sofa-search
- Seller: https://agentstack.voostack.com/s/komluk
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
