# Custom Agent Integration

> Markdown variant of <https://www.skillzdrive.com/docs/agent-integration>.
> For developers building custom agents that connect directly to
> SkillzDrive via MCP.

If you use Claude Code, Cursor, Claude.ai, ChatGPT, or another client
with built-in MCP support, you don't need this page — follow the
[Quickstart](https://www.skillzdrive.com/docs/quickstart.md) instead.

## A. Making your agent aware of skills

### Baseline: install the guide skill

Connecting MCP and expecting the AI to use it is the #1 integration
mistake. **Most LLMs will NOT call MCP tools unless explicitly told
to.**

Install the `skillzdrive-mcp-guide` skill locally alongside your
agent. Once installed, the MCP server's briefing (plus
`skills_getStarted`) teaches your agent all 29 tools, execution
workflows, error handling patterns, and fallback chains — no system
prompt engineering required.

### Pattern 1: Pinned skills for sub-agents

In orchestrator/sub-agent architectures, the orchestrator discovers
skills dynamically (via `searchSkills` or `listSkills`), then pins a
specific skill or script to a sub-agent for efficiency. The
sub-agent skips discovery entirely and goes straight to execution.

```ts
// Orchestrator: discover dynamically, then delegate
const { results } = await mcpClient.callTool("skills_searchSkills", {
  query: userTask, // e.g. "merge these PDFs"
});
const skill = results[0]; // best match

// Pin the skill slug to a sub-agent's context
const subAgentPrompt = `You are a ${skill.name} specialist.
Use skill slug: ${skill.slug}
Go directly to skills_listScripts → skills_runScript → skills_readFile → skills_closeSession.
Do NOT call searchSkills or listSkills — your skill is already assigned.`;

await spawnSubAgent(subAgentPrompt);
```

This is the most efficient pattern for production systems. The
orchestrator handles discovery once, and each sub-agent operates
with minimal tool calls. You can pin down to a specific script name
if the orchestrator already knows which script to run.

### Pattern 2: Caching strategy

Don't re-fetch skill lists on every message. Skills and scripts
don't change mid-conversation.

| What to cache | Cache duration | When to refresh |
|---------------|----------------|-----------------|
| `listSkills` results | Entire session | Agent restart |
| `listScripts` per slug | Entire session | Agent restart |
| `runScript` results | **Never cache** | Every execution is unique |

## B. UI feedback for tool calls

The #2 mistake: running skills silently. Users see nothing for 5–30
seconds and think the app is broken. **Always show what's happening.**

### What to show at each stage

| Stage | What to show | Example |
|-------|--------------|---------|
| `searchSkills` | "Searching for skills..." | Spinner + message |
| `listScripts` | "Found merge.py — preparing..." | Status update |
| `runScript` | "Processing your PDF..." | Progress indicator |
| `readFile` | "Reading results..." | Brief flash |
| Success | Formatted result | Code block or rendered output |
| Error | Error + suggestions | Alert with recovery action |

### Implementation pattern

```ts
agent.onToolCall((toolName, args) => {
  switch (toolName) {
    case "skills_searchSkills":
      showStatus("Searching for skills...");
      break;
    case "skills_listScripts":
      showStatus(`Loading scripts for ${args.skillSlug}...`);
      break;
    case "skills_runScript":
      showStatus(`Running ${args.scriptName}...`);
      break;
    case "skills_readFile":
      showStatus("Reading results...");
      break;
  }
});

agent.onToolResult((toolName, result) => {
  if (toolName === "skills_runScript") {
    if (result.exitCode === 0) {
      showStatus("Script completed successfully", "success");
    } else {
      showStatus(result.error || "Script failed", "error");
    }
  }
});
```

### Displaying errors well

SkillzDrive errors are structured for great UX. Use all the fields:

```jsonc
{
  "error": "skill_not_found",            // Machine-readable code
  "message": "No skill with slug 'pdff'",// Show this to users
  "suggestions": [                       // Show as recovery options
    "Did you mean 'pdf'?",
    "Use skills_searchSkills to find skills"
  ],
  "_workflow": {                         // Use for automatic recovery
    "nextSteps": [
      { "tool": "skills_searchSkills", "example": { "query": "pdf" } }
    ]
  }
}
```

Display pattern:

1. Show `message` as the error text.
2. Show `suggestions[0]` as a clickable recovery action.
3. Use `_workflow.nextSteps` to auto-recover if possible.
4. **NEVER show raw JSON-RPC errors to users.**

## C. Async script execution

Scripts can take 5–60 seconds. Don't make users wait silently.
Acknowledge immediately, show progress, notify when done.

### Recommended pattern

1. Start the script (`runScript` with `reuseSession: true`).
2. Acknowledge immediately ("I'm processing your request...").
3. Continue conversation — let users ask other questions while the script runs.
4. Await completion — script finishes, read output.
5. Notify with results ("Your PDF merge is complete!").

```ts
async function executeSkillAsync(
  mcpClient: McpClient,
  skillSlug: string,
  scriptName: string,
  args?: string[],
) {
  notify("Starting skill execution...", "loading");

  const runResult = await mcpClient.callTool("skills_runScript", {
    skillSlug,
    scriptName,
    args,
    reuseSession: true,
  });

  if (runResult.exitCode !== 0) {
    notify(`Error: ${runResult.error}`, "error");
    return null;
  }

  const output = await mcpClient.callTool("skills_readFile", {
    sessionId: runResult.sessionId,
    filePath: "/tmp/last_run.out",
  });

  notify("Skill completed!", "success");
  displayOutput(output.content);

  await mcpClient.callTool("skills_closeSession", {
    sessionId: runResult.sessionId,
  });

  return output.content;
}
```

If `output.hasMore` is true, paginate with `startLine` and `limit`.
The default returns the first 200 lines.

## D. Integration checklist

### Connection
- [ ] MCP client connected via Streamable HTTP.
- [ ] API key authenticated and connected.

### Skill awareness
- [ ] Skills listed in system prompt or pre-loaded at startup.
- [ ] Agent knows to call `listScripts` before `runScript`.
- [ ] Skill slugs cached (not re-fetched every message).
- [ ] Script names cached per skill.

### Execution
- [ ] Agent uses `reuseSession: true` for all script runs.
- [ ] Agent reads output via `readFile` (not from `runScript` response).
- [ ] Agent closes sessions when done.

### User experience
- [ ] UI shows loading state during script execution.
- [ ] UI shows formatted results on success.
- [ ] UI shows error message + suggestions on failure.

## Next steps

- [AI context system prompt](https://www.skillzdrive.com/docs/ai-context.md) — copy-paste into your model's context.
- [Discovering skills](https://www.skillzdrive.com/docs/guides/discovering-skills.md) — deep dive on search, browsing, and skill types.
- [Executing scripts](https://www.skillzdrive.com/docs/guides/executing-scripts.md) — session lifecycle, credentials, output handling.
