Skip to content

Service registry ​

The service registry describes the third-party APIs Overslash can act on. Each service is one OpenAPI 3.1 document with a small set of Overslash vendor extensions (x-overslash-*) that add the things OpenAPI doesn't model: a stable service key, a per-action risk level, permission scoping, and approval-time disclosure. Built-in services live in the source repo's services/ directory; orgs can register custom services through the API.

Pre-release

The schema is stabilising; expect field renames before the first tagged release.

File layout ​

One file per service in services/, with a .yaml or .yml extension. At startup every file is parsed as OpenAPI 3.1, its aliases are normalized, and it is compiled into the in-memory service definition that the executor uses. A file that fails to parse, compile, or validate is logged and skipped — one broken template can't take down the process — so check the server logs after adding a service.

A synthetic http pseudo-service is always present (it backs raw HTTP passthrough) unless a shipped file claims the http key. You don't author it; see Raw HTTP passthrough.

Schema ​

Overslash reads a standard OpenAPI 3.1 document and maps it onto its own model. The extension fields can be written bare (risk:, scope_param:, key:) — the loader normalizes them to their canonical x-overslash-* form — so the shipped files stay readable. The mapping:

Top level ​

OpenAPI fieldMaps toRequiredNotes
openapi—yesMust be 3.1.0.
info.titledisplay nameyesHuman-readable service name.
info.keyservice keyyesStable identifier (e.g. github). Used everywhere the API refers to the template.
info.descriptiondescriptionnoOne-line summary.
info.categorycategorynoGrouping label (e.g. Development, Communication).
servers[].urlhostsyesOne or more base URLs; their hostnames bind the service.
components.securitySchemesauth methodsnoSee Auth.
pathsactionsnoOne action per path × HTTP method. See Actions.

Auth ​

Each entry under components.securitySchemes is one auth method.

OAuth (type: oauth2)

FieldRequiredNotes
provideryesOAuth provider key (e.g. github, google, slack).
flows.authorizationCode.authorizationUrl / tokenUrlyesStandard OAuth endpoints.
flows.authorizationCode.scopesnoThe superset of scopes the service may request. The caller picks the subset to request at connect time; the provider's granted scopes are recorded on the connection.

API key (type: apiKey)

FieldRequiredNotes
inyesheader or query.
nameyesHeader or query-parameter name.
x-overslash-prefixnoString prepended to the value (e.g. "Bearer ").
default_secret_nameyesName of the vault secret holding the key.

Actions ​

Each paths.<path>.<method> operation is one action.

FieldRequiredDefaultNotes
operationIdyes—The action key callers invoke.
summaryyes—Human-readable description. Supports {param} interpolation and [optional segments] that are dropped when the referenced param is absent.
risknofrom methodread, write, or delete. When omitted, defaults from the HTTP method (GET → read, etc.). Drives whether an action needs approval and whether overslash_read will run it.
scope_paramno*Which parameter supplies the {arg} segment of the permission key. Without it the arg defaults to * (the whole action).
securitynoservice scopesPer-action minimum OAuth scopes, checked against the connection's granted scopes at call time.
parametersno—See Parameters.
requestBodyno—Standard OpenAPI request body (content.application/json.schema).

Disclosure and visibility extensions on an action:

FieldNotes
discloseList of { label, filter, max_chars? }. Each filter is a jq expression over a {method, url, params, body} projection of the resolved request; the extracted values are shown in the approval UI and audit log. max_chars clamps long strings (e.g. email bodies).
redactDotted paths into the resolved request to replace with "[REDACTED]" in the persisted payload.
response_typejson (default) or binary (file downloads).
disabledWhen true, hides the action and rejects invocation.

Parameters ​

Each entry in an action's parameters list:

FieldRequiredNotes
nameyesParameter name.
inyespath or query.
requirednoDefaults to false (path params are required).
descriptionnoShown to agents.
schema.typeyesstring, integer, boolean, …
schema.enumnoAllowed values.
schema.defaultnoDefault value.
resolveno{ get, pick } resolver that turns an opaque ID into a human-readable name for descriptions: get is a GET path with {param} placeholders (reusing the service's auth), pick is a dot-path into the JSON response.

Runtime ​

Most services are HTTP. The runtime extension can also be mcp (actions are tools on an external MCP server, configured by an mcp block) or platform (actions dispatch to in-process Rust handlers). These are advanced; HTTP is the common case documented above.

Examples ​

The three shipped files below are the canonical worked examples.

A read-only action ​

From services/github.yaml — OAuth service, two read actions. list_repos shows query parameters with an enum and a default, and the [, sorted by {sort}] optional segment in the summary:

yaml
openapi: 3.1.0
info:
  title: GitHub
  key: github
  category: Development
servers:
  - url: https://api.github.com
components:
  securitySchemes:
    oauth:
      type: oauth2
      provider: github
      flows:
        authorizationCode:
          authorizationUrl: https://github.com/login/oauth/authorize
          tokenUrl: https://github.com/login/oauth/access_token
          scopes:
            repo: ""
            read:user: ""
            user:email: ""
paths:
  /user:
    get:
      operationId: get_authenticated_user
      summary: Get the authenticated user's profile
      risk: read
  /user/repos:
    get:
      operationId: list_repos
      summary: "List repositories for the authenticated user[, sorted by {sort}]"
      risk: read
      parameters:
        - name: sort
          in: query
          description: Sort by created, updated, pushed, full_name
          schema:
            type: string
            enum: [created, updated, pushed, full_name]
        - name: per_page
          in: query
          description: Results per page (max 100)
          schema:
            type: integer
            default: 30

A write action ​

From services/slack.yaml — a risk: write action with scope_param (the permission key is anchored on channel) and a JSON requestBody:

yaml
openapi: 3.1.0
info:
  title: Slack
  key: slack
  category: Communication
servers:
  - url: https://slack.com
  - url: https://api.slack.com
components:
  securitySchemes:
    oauth:
      type: oauth2
      provider: slack
      flows:
        authorizationCode:
          authorizationUrl: https://slack.com/oauth/v2/authorize
          tokenUrl: https://slack.com/api/oauth.v2.access
          scopes:
            chat:write: ""
            channels:read: ""
paths:
  /api/chat.postMessage:
    post:
      operationId: send_message
      summary: Send a message to Slack channel {channel}
      risk: write
      scope_param: channel
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [channel, text]
              properties:
                channel:
                  type: string
                  description: Channel ID
                text:
                  type: string
                  description: Message text
  /api/conversations.list:
    get:
      operationId: list_channels
      summary: List Slack channels

For a richer write example, services/gmail.yaml's send_message uses disclose to decode the base64url RFC 2822 payload and surface the To / Subject / Body in the approval review UI — the pattern for making an opaque body human-reviewable.

Raw HTTP passthrough ​

The synthetic http pseudo-service backs raw HTTP calls. You don't author a file for it; conceptually it is a service with no hosts (the caller supplies the full URL) and no template-bound auth (only per-call secret injection):

yaml
# Conceptual shape of the built-in `http` pseudo-service — not a file you write.
info:
  key: http
  title: Raw HTTP
  category: Platform
servers: []        # no host binding — caller supplies the full URL
# no securitySchemes — per-call secrets only

Invoke it with overslash call --url … (CLI, Mode A) or POST /v1/actions/call with service: "http" (REST → Actions). Note that raw HTTP is not expressible through the overslash_call MCP tool — it's REST/CLI only.

Validating ​

Shipped templates are validated as they load; anything that fails parse, compile, or validation is logged as an error and skipped rather than served. After adding or editing a file, restart and check the logs for a skipping line naming your file.

Registering a custom service ​

Orgs can register their own services at runtime through the REST API rather than shipping a file. See REST → Services for the endpoints, and Concepts → Services & actions for how a service definition relates to a runtime action.

Pre-release software — subject to change without notice.