Skip to content

feat(actions,vendo): any REST API with a spec becomes agent tools - #1465

Closed
yousefh409 wants to merge 2 commits into
mainfrom
yousefh409/ingest-s2-openapi
Closed

feat(actions,vendo): any REST API with a spec becomes agent tools#1465
yousefh409 wants to merge 2 commits into
mainfrom
yousefh409/ingest-s2-openapi

Conversation

@yousefh409

@yousefh409 yousefh409 commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds openApiConnector({ spec, baseUrl, headers, name }) — turns an OpenAPI document into guarded agent tools. It is reuse, not new machinery: the same extractor vendo sync runs over a spec file, and the same HTTP dispatch a host tool executes through, both refactored to be shared rather than duplicated.

Two factorings made the sharing possible:

  • extractOpenApi's document-level half moved to the pure packages/actions/src/openapi-document.ts; sync/openapi.ts keeps the node:fs and spec-file entry points, and the connector is handed the document in memory instead.
  • registry.ts's HTTP leg (argument binding, path substitution, the tRPC envelope, the fetch) is now packages/actions/src/runtime/http-dispatch.ts, used by both the registry and the connector.

McpAuthContext / McpHeadersResolver stay working as deprecated aliases of the new ConnectorAuthContext / ConnectorHeadersResolver. Both connectors are re-exported from @vendoai/vendo/server (and vendoai/server), and docs-site/capabilities/connectors.mdx documents them — mcpConnector's first page.

Public surface

packages/actions/src/connectors/openapi.ts:

export interface ConnectorAuthContext { principal?; presence?; grant?; }
export type ConnectorHeadersResolver = (auth: ConnectorAuthContext) => Promise<Record<string,string>> | Record<string,string>;
export function openApiConnector(config: {
  spec: string | Record<string, unknown>; // JSON/YAML text or parsed object; never a path/URL
  baseUrl?: string;                        // wins over spec servers[0]
  headers?: Record<string,string> | ConnectorHeadersResolver;
  name?: string;
}): Connector;

Tool names normalize under openapi_<name>; risk derives from extractedRisk(method).

Net effect

Nets −482/+104 lines by de-duplicating the OpenAPI extractor and HTTP dispatch instead of adding a parallel implementation.

Testing

7 tests stand up a live in-test HTTP fixture server and execute through createActions — no stub on either side. They prove the round trip, that baseUrl beats servers[0], that a headers resolver sees the principal and grant, and that risk tracks the method. Full @vendoai/actions package: 651 tests passing.

Stack

Part of a 4-PR stack (data ingestion + custom tools + connectors + tenant connectors). This PR is based on the defineTool PR (#1464) and is the second-from-bottom of the stack. The merge unit is the stack tip — this PR is a review window, not an independent merge.

🤖 Generated with Claude Code


Summary by cubic

Turns any OpenAPI document into guarded agent tools at runtime via openApiConnector({ spec, baseUrl, headers, name }). Previously specs only produced host tools at sync; now the connector reuses the same extractor and HTTP dispatch for identical behavior.

  • Shared extractor: document parsing lives in packages/actions/src/openapi-document.ts; sync/openapi.ts now only reads files. Route naming and method-based risk moved to binding-identity.ts (re-exported from sync/common.ts).
  • Shared HTTP dispatch: request building, tRPC envelope, and fetch live in packages/actions/src/runtime/http-dispatch.ts and are used by both the registry and connector; JSON accept/content-type are set inside fetchHostTool.
  • Tool surface: tools are named openapi_<name>_<operationId> (collisions throw). Risk derives from method (DELETEdestructive, others ungraded). baseUrl passed to the connector overrides the spec’s absolute servers[0]; relative servers fall back to the host origin.
  • Auth context/exports: new ConnectorAuthContext/ConnectorHeadersResolver enable per-call headers; McpAuthContext/McpHeadersResolver remain as deprecated aliases. Both connectors are exported from @vendoai/vendo/server.
  • Security/portability: spec is the document itself (JSON/YAML text or object), never a path or URL.
  • Docs/tests: documented at /capabilities/connectors. Live HTTP tests cover round trips, baseUrl precedence, per-call headers (principal/grant), YAML parsing, and method-based risk.

Migration

  • No changes required for existing hosts. MCP users may switch to ConnectorAuthContext/ConnectorHeadersResolver when convenient.
  • To adopt: import openApiConnector from @vendoai/vendo/server, pass the spec document, optionally set baseUrl, and provide headers (object or resolver) if you need dynamic auth.

Written for commit 422267b. Summary will update on new commits.

Review in cubic

@greptile-apps

greptile-apps Bot commented Aug 18, 2026

Copy link
Copy Markdown

Greptile Summary

Adds an OpenAPI connector that converts in-memory REST specifications into agent tools, sharing the existing extraction and HTTP request execution behavior. Local-server coverage confirms configured base URLs, path and query serialization, JSON request bodies, response handling, and per-call authentication headers work together.

Confidence Score: 5/5

No blocking failure remains.

There are no accepted P0 or P1 findings.

Reviews (3): Last reviewed commit: "chore: changeset for the OpenAPI connect..." | Re-trigger Greptile

Comment thread packages/actions/src/openapi-document.ts
@yousefh409
yousefh409 force-pushed the yousefh409/ingest-s2-openapi branch from 7ead67b to 29f79ae Compare August 18, 2026 12:53
Comment thread packages/actions/src/openapi-document.ts
yousefh409 and others added 2 commits August 18, 2026 20:11
openApiConnector({ spec, baseUrl, headers, name }) turns an OpenAPI
document into guarded tools. It is reuse, not new machinery: the same
extractor `vendo sync` runs over a spec file, and the same HTTP dispatch
a host tool executes through.

Two factorings made that sharing possible:

- extractOpenApi's document half moved to the pure src/openapi-document.ts
  (the binding-identity.ts precedent). sync/openapi.ts keeps node:fs and
  the spec-file entry points; the connector is handed the document in
  memory. Keeping it in sync/ would have dragged sync/common.ts and its
  TypeScript compiler into the runtime entry, which the portability gate
  forbids outright (FORBIDDEN_INPUTS: packages/actions/dist/sync/).
  Route naming and extractedRisk moved alongside it into
  binding-identity.ts, re-exported from sync/common.ts.
- registry.ts's HTTP leg — argument binding, path substitution, the tRPC
  envelope, the fetch — is runtime/http-dispatch.ts now, used by the
  registry and the connector both. The JSON accept/content-type envelope
  moved inside fetchHostTool, so neither caller sets it.

McpAuthContext and McpHeadersResolver stay working as deprecated aliases
of ConnectorAuthContext / ConnectorHeadersResolver. Both connectors are
re-exported from @vendoai/vendo/server (and so from vendoai/server), and
docs-site/capabilities/connectors.mdx documents them — mcpConnector's
first page.

The test stands up a live HTTP fixture, points the connector at a spec
describing it, and executes through createActions: no stub on either
side. It proves the round trip, that baseUrl beats servers[0], that a
headers resolver sees the principal and grant, and that risk tracks the
method.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@yousefh409
yousefh409 force-pushed the yousefh409/ingest-s2-openapi branch from 29f79ae to 422267b Compare August 18, 2026 20:22
@mintlify

mintlify Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
Vendo 🟢 Ready View Preview Aug 18, 2026, 8:23 PM

@yousefh409

Copy link
Copy Markdown
Collaborator Author

Landed on main as part of the ingest stack via #1473 (squash 6bc5cc851). Closing — the squash merge cannot mark this PR merged automatically.

@yousefh409 yousefh409 closed this Aug 18, 2026
@yousefh409
yousefh409 deleted the yousefh409/ingest-s2-openapi branch August 18, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant