> ## Documentation Index
> Fetch the complete documentation index at: https://docs.toolshed.philo.ventures/llms.txt
> Use this file to discover all available pages before exploring further.

# Core Concepts

> The building blocks of Toolshed -- tools, plugins, sources, roles, and elicitation.

## Tools

A tool is an atomic operation with a typed input schema, optional output schema, and a handler function. Every tool has a **path** (dot-separated lowercase identifier like `github.issues.create`) and a **name** (Title Case like "Create Issue").

Tools are the fundamental unit of the Toolshed catalog. Agents discover tools via `search_tools`, inspect them via `read_tool`, and invoke them inside sandbox scripts.

## Plugins

A plugin groups related tools with shared authentication. Plugins are defined using the SDK's `definePlugin` and `defineTool` functions:

```typescript theme={null}
import { definePlugin, defineTool } from "@toolshed/sdk";

const myPlugin = definePlugin({
  id: "my-service",
  name: "My Service",
  description: "Tools for My Service",
  authProviders: [{ id: "my-service", type: "oauth2", provider: "my-service", scopes: ["read"] }],
  tools: [
    defineTool({
      path: "my_service.items.list",
      name: "List Items",
      description: "List items from My Service",
      inputSchema: z.object({ limit: z.number().default(10) }),
      async handler(ctx, input) {
        const token = await ctx.auth.getToken("my-service");
        // call API...
      },
    }),
  ],
});
```

See [Writing Plugins](/guides/writing-plugins) for a full walkthrough.

## Sources

A source is a unit of tool registration. Sources are how external APIs get imported into the Toolshed catalog. Four adapter types are supported:

| Type        | What it does                                                                |
| ----------- | --------------------------------------------------------------------------- |
| **OpenAPI** | Fetches an OpenAPI/Swagger spec and auto-generates tools from endpoints     |
| **GraphQL** | Introspects a GraphQL schema and generates tools from queries and mutations |
| **MCP**     | Connects to an external MCP server and imports its tools                    |
| **Plugin**  | Wraps a hand-written plugin as a registry-compatible source                 |

See [Adding Sources](/guides/adding-sources) for configuration details.

## Roles and Policy

A role defines which tools a user can access using glob patterns:

```json theme={null}
{
  "id": "developer",
  "name": "Developer",
  "patterns": ["github.**", "linear.issues.*", "slack.channels.list"]
}
```

Pattern syntax:

* `github.issues.*` -- matches one segment (`github.issues.create`, `github.issues.list`)
* `github.**` -- matches any depth under `github`
* `*` -- matches everything (admin)

The policy engine filters the tool catalog at runtime so each user only sees tools their role permits. See [Policy and Roles](/guides/policy-and-roles).

## Elicitation

Destructive tools (those that create, update, or delete data) require human approval before executing. When a sandbox script calls a destructive tool:

1. Execution **pauses** and returns a `paused` result with an `executionId`
2. The agent presents the pending action to the user
3. The user approves or denies via the `resume` MCP tool
4. Execution continues or rejects based on the decision

This ensures a human is always in the loop for irreversible operations. See [Elicitation Guide](/guides/elicitation).

## The Tools Proxy

Inside sandbox scripts, tools are accessed through a property-chain proxy:

```typescript theme={null}
// Discover tools
const results = await tools.search({ query: "email" });

// Inspect a tool
const schema = await tools.describe.tool({ path: "gmail.messages.list" });

// Call a tool
const emails = await tools.gmail.messages.list({ query: "from:acme" });
```

The proxy translates `tools.gmail.messages.list(args)` into an invocation of tool path `gmail.messages.list`. Agents cannot enumerate the proxy -- they must use `tools.search()` to discover available tools.
