---
title: "AI Connector Guide"
slug: help-ai-connector
section: In-App Help
status: stable
description: "Read-only HTTP surface for ChatGPT Custom GPTs, Manus, Cursor, and any tool that consumes OpenAPI 3.1."
last-updated: 2026-10-07
---

# AI Connector Guide

Read-only HTTP surface for ChatGPT Custom GPTs, Manus, Cursor, and any tool that consumes OpenAPI 3.1.

> **Read-only by design**
>
> The AI Connector exposes the Globus ecosystem docs site, delivery goals, project status, team capacity, and audit events to external AI tools. It never writes — no mutation endpoints exist on this surface. MCP coordination (the protocol the internal portals speak) is a separate workstream and is explicitly not wired through here.

> **See also: AI Connector — MCP server activation spec**
>
> For MCP-native clients (Claude Desktop, Cursor, Windsurf), the same /api/ai/v1/* surface is wrapped by a separate MCP coordination server. The contract that MCP server must implement — transport, tool list, resources, audit/rate-limit propagation, and end-user connect snippets — lives at AI Connector — MCP server activation spec. This page (OpenAPI surface) and that page (MCP surface) are the two halves of the AI Connector.

## What This Surface Is

Every endpoint lives under /api/ai/v1/* and is a thin shaper over the same aggregate fetchers the docs site itself uses (combined Asana summary, team capacity, project ownership, audit log). The shape is intentionally smaller and slug-keyed so an AI tool can call listGoals &rarr; getGoalStatus(goalId) &rarr; listProjects(goalId) without knowing anything about Asana GIDs.

The Globus docs site renders content as React components rather than storing markdown bodies. getDoc(slug) reads the page's MDX source (falling back to the legacy TSX source for pages not yet migrated) and converts it to markdown — consumers receive a real body string and a bodyFormat: "markdown" flag. For dynamic / data-driven pages where extraction yields nothing the response falls back to bodyFormat: "structured-only" with body: null, and consumers should follow the permalink for the authoritative rendered article. The same extracted bodies feed searchDocs, which is therefore genuine full-text search — body matches return a short snippet alongside the slug + permalink so the AI consumer can ground its answer without a follow-up getDoc call.

## Authentication

Every request must carry an AI Consumer API Key. This is a different credential from the staff admin key (SESSION_SECRET) and from any partner-portal session token. Two header forms are accepted — pick whichever your tool prefers:

# Option 1 — Bearer token (works with ChatGPT Actions, Manus, curl)

Authorization: Bearer aik_

# Option 2 — Dedicated header (preferred for tools with a custom auth slot)

x-ai-key: aik_

> **Keys are not user-scoped**
>
> AI Consumer keys identify a tool, not a person. The actor recorded on every audit row is ai-consumer: (e.g. ai-consumer:chatgpt-marketing). Issue separate keys per tool so the audit trail stays meaningful.

## Rate Limits & Auditing

| Limit | Value | Notes |
| --- | --- | --- |
| Per-key rate limit | 30 requests / minute | Keyed on the AI Consumer key value (from x-ai-key or the bearer token), not on the source IP — so ChatGPT, Manus, and Cursor each get their own 30/min bucket even when they egress from shared cloud IP ranges. Stricter than the 120/min general API limit. Returns HTTP 429. |
| Audit emission | Every authenticated request, whatever the status (rate-limited calls are logged with a `.ratelimited` action suffix; unauthenticated 401s are not audited) | Action names: ai.docs.list, ai.docs.search, ai.docs.batch, ai.docs.get, ai.goals.list, ai.goals.get, ai.projects.list, ai.projects.get, ai.team_capacity.get, ai.audit.list, ai.system_context.get. Entity type is ai_request. |
| Audit query | Available via /api/ai/v1/audit | Filter by actionPrefix=ai. to see only AI-consumer traffic. |

## OpenAPI 3.1 Document

The OpenAPI document is hosted at well-known paths so any compliant tool can discover the surface without prior configuration:

GET /.well-known/openapi-ai.json → OpenAPI 3.1 spec (JSON)

GET /.well-known/openapi-ai.yaml → OpenAPI 3.1 spec (YAML)

The spec itself is unauthenticated — AI tools fetch it during setup before the operator configures the consumer key. Each endpoint declares an x-stability extension (currently beta across the board for v1).

## Endpoint Catalog

| Operation | Method & Path | Purpose |
| --- | --- | --- |
| listDocs | GET /api/ai/v1/docs | Section-grouped manifest of every doc page. |
| searchDocs | GET /api/ai/v1/docs/search?q= | Full-text search across titles, headings, glossary terms, and the extracted markdown body of every page. Body matches include a short snippet. |
| getDoc | GET /api/ai/v1/docs/:slug | Metadata + headings + permalink + markdown body extracted from the React source (bodyFormat: 'markdown', or 'structured-only' when extraction yields nothing). |
| listGoals | GET /api/ai/v1/goals | All delivery goals with blended Dev/UAT/Deploy progress. |
| getGoalStatus | GET /api/ai/v1/goals/:goalId | Single goal — same shape as listGoals[i]. |
| listProjects | GET /api/ai/v1/projects?goalId=&stream= | Every Asana-backed project, optionally scoped to a goal or stream. |
| getProjectStatus | GET /api/ai/v1/projects/:projectId | One project by code (P3, HP-7, AP-1) or by Asana gid. |
| getTeamCapacity | GET /api/ai/v1/team-capacity | Per-person totals, completion, projects, and phase rollup. |
| listAuditEvents | GET /api/ai/v1/audit | Paginated audit log. AI requests recorded here too — query actionPrefix=ai. to see only AI traffic. |
| getDocsBatch (MCP tool; not in the OpenAPI document) | GET /api/ai/v1/docs/batch?slugs= | Markdown bodies for up to 20 comma-separated slugs in one call. |
| system context (not in the OpenAPI document) | GET /api/ai/v1/system-context | Single boot call: goals summary, doc index grouped by section, and infra hints. |

## Setup — ChatGPT Custom GPT Action

Open the Custom GPT editor → Configure → Actions → Create new action. / Click 'Import from URL' and paste https:// /.well-known/openapi-ai.json. / Under Authentication, choose 'API Key' → Auth Type 'Bearer' → paste the AI Consumer key (starts with aik_). / Save. Test by asking the GPT 'list Globus delivery goals' — it should call listGoals and return the blended progress table.
## Setup — Manus / Generic OpenAPI Tool

Point your tool at the OpenAPI document URL (/.well-known/openapi-ai.json or .yaml). / Configure the AiConsumerKey security scheme — supply the key via either Authorization: Bearer or x-ai-key header. / Run a smoke test against GET /api/ai/v1/goals. A 200 with a goals array confirms the wiring. / Add the operation IDs (listGoals, getProjectStatus, searchDocs, etc.) to the tool's allow-list so the model can call them.
## Key Issuance & Rotation

There are two ways to issue and revoke AI Consumer keys:

- Staff UI (preferred for in-flight changes): the AI Tool Keys console calls /api/ai/keys (gated by the x-admin-password header, which must match AI_KEYS_ADMIN_PASSWORD) to mint, list, and revoke keys. New keys are usable by /api/ai/v1/* immediately — no restart. Every issuance and revocation is written to the audit log under the ai_consumer_key. action prefix. Keys are persisted in Postgres (ai_consumer_keys table) so they survive restarts; revocations take effect on the next request.
- Environment variable (preferred for durable production keys): set AI_CONSUMER_KEYS and restart. Format:
AI_CONSUMER_KEYS="chatgpt-marketing:aik_abc123,manus-research:aik_def456"

When AI_CONSUMER_KEYS is unset outside production, the server derives two deterministic dev keys (chatgpt-dev and manus-dev) from SESSION_SECRET so the surface is testable in Replit without manual provisioning. Dev token values are logged at boot under [ai-connector].

> **Production keys belong in the admin screen**
>
> Use the AI Tool Keys screen for real consumers. Env-var seeding is a backstop, and the dev-seed keys are deliberately not loaded in production unless AI_CONNECTOR_DEV_KEYS=true is set.

## Stability & Change Registry

The AI surface is registered against the same stability tier vocabulary used by the rest of the API platform (see Integration Contract → API Platform → Endpoint Stability Tiers). Every endpoint on /api/ai/v1/* is currently beta — the shape is settled but additive evolution is allowed without a major version bump.

Breaking changes will bump the URL namespace (/api/ai/v2/*) so configured Custom GPTs / Manus tools keep working until the operator chooses to upgrade. Additions are captured in the API change registry under the action prefix ai_connector..

## Scope Limits

markdown / structured-only
