---
name: Ivy Biosciences
homepage: https://www.ivybiosciences.com
contact: admin@ivybiosciences.com
protocol: auth.md
version: 0.1
---

# Auth.md

> Auth.md metadata for the Ivy Biosciences agent platform. See the
> [Auth.md specification](https://github.com/workos/auth.md) for the
> document contract.

## Ivy Biosciences — Authentication for agents

This document describes how AI agents authenticate to the Ivy Biosciences
biomedical-discovery agent API and MCP server.

## Quick discovery

| Resource | URL |
|---|---|
| OAuth 2.0 / OIDC discovery | `https://www.ivybiosciences.com/.well-known/openid-configuration` |
| OAuth authorization server metadata | `https://www.ivybiosciences.com/.well-known/oauth-authorization-server` |
| Protected resource metadata | `https://www.ivybiosciences.com/.well-known/oauth-protected-resource` |
| MCP server card | `https://www.ivybiosciences.com/.well-known/mcp/server-card.json` |
| Platform skill (ask Ivy, or submit one job) | `https://www.ivybiosciences.com/SKILL.md` |
| Agent skills index | `https://www.ivybiosciences.com/.well-known/agent-skills/index.json` |
| API catalog (RFC 9727) | `https://www.ivybiosciences.com/.well-known/api-catalog` |
| OpenAPI 3.1 spec | `https://www.ivybiosciences.com/openapi.json` |

## Agent registration

```yaml
agent_auth:
  skill: https://www.ivybiosciences.com/auth.md
  register_uri: https://clerk.ivybiosciences.com/oauth/register
  methods:
    - type: oauth2_authorization_code_pkce
      authorization_endpoint: https://clerk.ivybiosciences.com/oauth/authorize
      token_endpoint: https://clerk.ivybiosciences.com/oauth/token
      response_type: code
      grant_type: authorization_code
      code_challenge_method: S256
      scopes: [openid, profile, email, ivy:agent:run]
    - type: oauth2_client_credentials
      token_endpoint: https://clerk.ivybiosciences.com/oauth/token
      grant_type: client_credentials
      scopes: [ivy:agent:run]
```

Agents should use the authorization-code method with PKCE when acting on behalf
of a user. Use client credentials only for an operator-provisioned service
account; the client secret must never be exposed to a browser or forwarded to
the Ivy API.

## Identity provider

Ivy Biosciences uses [Clerk](https://clerk.com) as its OAuth 2.0 / OIDC
identity provider. The authoritative issuer is `https://clerk.ivybiosciences.com`.
The Ivy origin proxies `/.well-known/openid-configuration` and
`/.well-known/oauth-authorization-server` for discovery convenience.

## How agents should authenticate (ordered by friction)

Pick the lowest-friction option that meets your quota needs. Most autonomous agents
start at level 1 and only upgrade when they hit guest limits.

### 1. Anonymous (default, zero config)

Skip auth entirely. Just call the API:

```bash
curl -N -X POST https://www.ivybiosciences.com/api/v1/orchestrate \
  -H "Content-Type: application/json" \
  -d '{"prompt":"find papers on EGFR L858R","stream":true}'
```

Guest limits: up to 18 orchestrate calls per day per IP and $1 of compute per
IP per UTC day, metered from measured usage of Ivy's model calls; whichever
runs out first refuses the call. Both reset at UTC midnight and are shared
across all tools, not a per-tool allowance. Read `X-RateLimit-Remaining`
(calls) and `X-Compute-Budget-Remaining-USD` (dollars) on each response rather
than counting locally. Spent calls return 429 `GUEST_QUOTA_EXCEEDED`; a spent
budget returns 429 `GUEST_COST_LIMIT`; a busy guest pool returns 503
`GUEST_CAPACITY_REACHED` with `Retry-After`. No registration step.

### 2. API key (higher quota, single header)

Get a key from <https://www.ivybiosciences.com/settings/api-keys> (a human must
sign in with Google/email to claim one; takes ~30 s). Then:

```bash
curl -N -X POST https://www.ivybiosciences.com/api/v1/orchestrate \
  -H "Authorization: Bearer ivy_xxx" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"fold EGFR with L858R+T790M","stream":true}'
```

Or the alternate header form: `-H "X-Ivy-Api-Key: ivy_xxx"`.

Keys are scoped to a user account and inherit that account's subscription tier
(Seed / Grow / Flourish / Team / Enterprise). Quota is consumed against the key
owner. Revoke any key from the same console.

### 3. User-delegated OAuth (agent acts on behalf of an end user)

Standard OAuth 2.0 Authorization Code with PKCE. Redirect users to
`https://clerk.ivybiosciences.com/oauth/authorize` with
`scope=openid profile email ivy:agent:run`. The agent gets a `Bearer <jwt>` it
uses against `/api/v1/*`. Use this when the calling user owns the subscription
and you need their data context (chats, jobs, passports).

### 4. Service account (autonomous agent acts as itself)

OAuth 2.0 Client Credentials. Create an org-scoped service account in the
[Ivy console](https://www.ivybiosciences.com/settings/api-keys), POST to
`https://clerk.ivybiosciences.com/oauth/token` with `client_id` + `client_secret`,
use the returned JWT. Use this for scheduled jobs, CI, or always-on agent backends.

For dynamic client registration (RFC 7591), POST to
`https://clerk.ivybiosciences.com/oauth/register`.

### Footnote — humans using MCP clients

If you are a **human** running Claude Desktop, Cursor, Claude Code, or another
MCP client, install the `ivybloom` CLI and let it broker auth on your behalf —
see the [MCP delivery section](#mcp-delivery) below. **This path is not for
autonomous agents** — it requires a one-time browser-based login.

## Credentials

| Credential type | Header | Lifetime |
|---|---|---|
| OAuth 2.0 access token | `Authorization: Bearer <jwt>` | 1 hour |
| Refresh token | (token endpoint only) | 30 days, rotating |
| Session token | `Authorization: Bearer <session-jwt>` | Tied to user session |
| API key (service account) | `Authorization: Bearer ivy_sk_…` | Until revoked |

All bearer tokens are JWTs signed RS256. JWKS is at
`https://clerk.ivybiosciences.com/.well-known/jwks.json`.

## Scopes

| Scope | Grants |
|---|---|
| `openid` `profile` `email` | Standard OIDC identity claims |
| `offline_access` | Refresh tokens |

Today, all Ivy API access is bearer-token-gated against the authenticated user's
Clerk session — no fine-grained Ivy-specific OAuth scopes are enforced. Fine-grained
scopes (`ivy:jobs:read`, `ivy:jobs:write`, etc.) are reserved for a later release.

Billing-related actions (subscription checkout, credit top-ups) are gated by an
active authenticated session rather than scopes; the agent should redirect the
user to `https://www.ivybiosciences.com/pricing` to complete purchase.

## Revocation

Revoke a token via `POST https://clerk.ivybiosciences.com/oauth/revoke` with
`token=<value>` (RFC 7009). The server-side claim cache invalidates within 60 s.

API keys can be revoked directly from the Ivy console.

## MCP delivery

Ivy's Model Context Protocol server is **not** a hosted HTTP endpoint. It ships
as part of the [`ivybloom` CLI](https://www.ivybiosciences.com/cli/install).

To wire it into Claude Code / Cursor / Claude Desktop:

```bash
npm install -g @ivybiosciences/ivybloom-cli
ivybloom auth login --browser              # one-time OAuth via Clerk
```

```jsonc
// .mcp.json (Claude Code, Cursor)
{
  "mcpServers": {
    "ivybloom": {
      "command": "ivybloom",
      "args": ["mcp", "serve"]
    }
  }
}
```

The CLI holds the user's tokens in the system keychain and refreshes them
transparently. The MCP server transport is stdio, so no inbound OAuth flow at
the MCP layer is required.

Full discovery: `/.well-known/mcp/server-card.json`.

## Claim verification

Receiving the access token's `aud` claim:
- For Ivy APIs: `aud = "https://www.ivybiosciences.com/api"`.

Verify the JWT signature against the JWKS, check `iss = "https://clerk.ivybiosciences.com"`,
`exp` in the future, and the required scope is present in `scope` (space-delimited).

## Contact

Security or auth concerns: `admin@ivybiosciences.com` or
`https://www.ivybiosciences.com/.well-known/security.txt`.
