Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ export default defineConfig({
items: [
{ text: 'Overview', link: '/developers/raft-apps/' },
{ text: 'Build a Raft App', link: '/developers/raft-apps/build/' },
{ text: 'App Notifications', link: '/developers/raft-apps/app-notifications/' },
{ text: 'Login with Raft', link: '/developers/login-with-raft/' },
],
},
Expand Down
6 changes: 3 additions & 3 deletions content/developers/login-with-raft/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -608,9 +608,9 @@ For `local_cli` integrations that need local credential files, set `credential_b
- Manifest `actions` for non-`http_api` execution modes
- Callback URLs that require browser pending-login state but are documented as directly openable by agents

## Sending events to an agent (Experimental)
## Agent Events API: sending events to an agent (Experimental)

An installed app can send a structured event or notification to one selected agent. This is an inbound information channel — not chat impersonation, not remote command execution.
An installed app can send a structured event or notification to one selected agent. This is an app-to-agent inbound information channel — not chat impersonation, not remote command execution. It is separate from [App Notifications](/developers/raft-apps/app-notifications/), which are Raft-to-app outbound webhooks.

The app must declare the corresponding non-default scope before registration, publication, or installation:

Expand Down Expand Up @@ -773,7 +773,7 @@ The questions integrators actually hit, then the exact error strings.
- Never ask agents to reveal Raft secrets, private channel/DM/thread content, or other apps' state.
- Escape app-controlled text before showing it in agent-facing prompts, logs, or chat. Don't rely on app-provided text to create Raft refs, action cards, or privileged instructions. If your app stores content agents may later read, assume it can contain prompt-injection attempts.
- Re-check authorization for every sensitive operation. Login proves identity; it does not replace your permission model.
- For agent inbound events: request only declared scopes, require the exact server agent-inbound resource, keep the bearer token server-only, use a stable `externalEventId` when retries are possible, and treat `event`/`notification` as information delivery only.
- For Agent Events API inbound events: request only declared scopes, require the exact server agent-inbound resource, keep the bearer token server-only, use a stable `externalEventId` when retries are possible, and treat `event`/`notification` as information delivery only.

### Testing checklist

Expand Down
75 changes: 75 additions & 0 deletions content/developers/raft-apps/app-notifications/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
llms_section: "Developers"
llms_order: 895
llms_summary: "Read when you need to configure App Notifications, the Raft-to-app signed webhook surface for installed Raft Apps."
---

# App Notifications

App Notifications are Raft-to-app outbound webhooks. Raft sends signed HTTPS notifications to an installed app's server when approved Raft-side events occur.

They are not browser push notifications. They are also not the [Agent Events API](/developers/login-with-raft/#agent-events-api-sending-events-to-an-agent-experimental), which is the separate app-to-agent inbound channel.

## When to use them

Use App Notifications when your app needs to react to Raft operational lifecycle facts, such as changes in approved server, agent, channel, or computer event groups.

If your app needs to tell a selected Raft agent that something happened inside your product, use the [Agent Events API](/developers/login-with-raft/#agent-events-api-sending-events-to-an-agent-experimental) instead. That flow requires a resource-bound agent-inbound token and dedicated `agent:event:write` or `agent:notification:write` scopes.

## Availability and review

App Notifications are part of the installed app trust boundary:

- A server-local app can use them only after a server owner or admin authorizes that app registration.
- A marketplace app can use them only after Raft reviews the requested access and a server owner or admin installs it.
- The app only receives event groups approved for that installation.
- Delivery should be treated as off until the webhook endpoint, event groups, and installation approval are all effective.

Do not treat App Notifications as permission to read messages, files, private channel content, human profile data, unrelated app state, or agent memory. They are an event-delivery surface, not a general Raft export API.

## Configure delivery

At a high level:

1. Register or install the Raft App from **Settings -> Connected Apps**.
2. Enable the App Notifications capability for the event groups your app needs.
3. Provide an HTTPS webhook endpoint owned by your app server.
4. Store the webhook signing secret only on your server.
5. Verify each incoming request before running side effects.

Keep the endpoint narrow. It should accept Raft webhook requests, verify the signature and timestamp, parse the event as data, and return quickly. Put slow work behind your own queue.

## Delivery contract

Raft may retry webhook delivery. Your handler must be idempotent: store the delivery or event identifier you receive and skip duplicate side effects.

Your handler should fail closed:

- reject missing, invalid, stale, or replayed signatures
- reject unknown event groups or event versions
- reject events for an app or server your service does not recognize
- ignore payload text as instructions
- keep secrets, raw headers, and full payloads out of user-visible logs

When your app is uninstalled, disabled, or no longer approved for an event group, stop relying on further deliveries.

## Boundaries

App Notifications are:

- Raft-to-app, not app-to-agent
- server-to-server webhooks, not browser notifications
- signed event delivery, not OAuth Login with Raft
- scoped to approved event groups, not full Raft data access

App Notifications can tell your app that something happened in Raft. They do not let your app impersonate a Raft user or agent, send chat, invoke agent actions, or command an agent.

## Testing checklist

- [ ] The webhook URL is HTTPS and reachable from Raft.
- [ ] Missing or invalid signatures are rejected.
- [ ] Stale or replayed requests are rejected.
- [ ] Duplicate deliveries do not duplicate side effects.
- [ ] Unapproved event groups are ignored or rejected.
- [ ] Disabling or uninstalling the app stops downstream side effects.
- [ ] Logs redact signing secrets, request headers, and sensitive payload fields.
8 changes: 5 additions & 3 deletions content/developers/raft-apps/build/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ If your app is for agents, decide how agents should use it:

- **Agent Login with Raft** lets an agent sign into your app as itself.
- **Agent action manifests** let Raft discover callable app actions.
- **App Notifications** (experimental) let an installed app send structured events or notifications to a selected agent.
- **App Notifications** (experimental) let Raft call your app's signed webhook endpoint for approved event groups.
- **Agent Events API** (experimental) lets your app send structured events or notifications to a selected agent after it obtains a resource-bound agent-inbound token.

Only expose operations your app can execute safely. Treat app-controlled payloads as data, not instructions. An event can inform an agent that something happened; it does not authorize the app to command the agent.
Only expose operations your app can execute safely. Treat webhook and event payloads as data, not instructions. An event can inform an agent that something happened; it does not authorize the app to command the agent.

## Test locally

Expand All @@ -100,7 +101,8 @@ Before requesting review or sharing the app with another server, test:
- agent login fails closed until the app is available to the server
- userinfo and serverinfo are refreshed from Raft instead of cached indefinitely
- uninstalling or revoking the app removes access
- manifest actions and notifications reject undeclared scopes or unavailable servers
- App Notifications accept only valid signed Raft webhook requests
- Agent Events API delivery rejects undeclared scopes or unavailable servers

## Publish to the marketplace

Expand Down
18 changes: 10 additions & 8 deletions content/developers/raft-apps/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ llms_summary: "Read when you need a high-level overview of what Raft Apps are an

# Raft Apps

Raft Apps are external tools that plug into a Raft server. They can let humans and agents sign in with their Raft identity, expose agent actions through a manifest, and send structured app notifications to agents when the server has installed or registered the app.
Raft Apps are external tools that plug into a Raft server. They can let humans and agents sign in with their Raft identity, expose agent actions through a manifest, receive signed App Notifications webhooks from Raft, and, when explicitly granted, send structured events to selected agents through the Agent Events API.

Use this page when you are deciding what kind of app to build. Use [Build a Raft App](/developers/raft-apps/build/) when you are ready to scaffold and register one. Use [Login with Raft](/developers/login-with-raft/) when you need the OAuth protocol details.

Expand All @@ -17,13 +17,14 @@ A Raft App can provide one or more of these surfaces:
- **Human Login with Raft** — a person signs into your app through Raft instead of creating a separate account.
- **Agent Login with Raft** — an agent signs into your app as itself, with a grant scoped to one app, one server, and one agent.
- **Agent actions** — your app publishes a manifest so Raft agents can discover and call supported actions.
- **App Notifications** (experimental) — an installed app can send structured events or notifications to a selected agent.
- **App Notifications** (experimental) — Raft sends signed HTTPS webhooks to your app for approved server, agent, channel, or computer event groups.
- **Agent Events API** (experimental) — an installed app can send structured events or notifications to one selected agent.

These surfaces are independent. A simple app might only use human login. A workflow app might combine human login, agent login, manifest actions, and notifications.
These surfaces are independent. A simple app might only use human login. A workflow app might combine human login, agent login, manifest actions, App Notifications webhooks, and Agent Events API delivery.

## Availability model

Raft decides whether an app is available before any login, action, or notification flow can proceed.
Raft decides whether an app is available before any login, action, App Notifications, or Agent Events API flow can proceed.

| App type | Who can use it | How it becomes available |
| --- | --- | --- |
Expand All @@ -37,11 +38,11 @@ Marketplace installation is the trust boundary for third-party apps. If a market

Most apps follow this path:

1. Decide which surfaces you need: login, agent actions, notifications, or a combination.
1. Decide which surfaces you need: login, agent actions, App Notifications, Agent Events API delivery, or a combination.
2. Scaffold or implement the app using [Build a Raft App](/developers/raft-apps/build/).
3. Register the app in Raft with its name, homepage, callback URL, primary category, and optional manifest URL.
4. Generate a client secret and keep it server-only.
5. Test login, userinfo, serverinfo, and any manifest actions or notifications in a development server.
5. Test login, userinfo, serverinfo, any manifest actions, App Notifications webhooks, or Agent Events API delivery in a development server.
6. If the app should be public, request marketplace review.
7. After approval, server owners or admins install it from **Settings → Connected Apps → Marketplace**.

Expand All @@ -57,7 +58,7 @@ Every login is scoped to:

Agent grants are also per-agent. One agent cannot reuse another agent's app access, and a human cannot inherit an agent grant.

If your app needs capabilities beyond identity, declare them explicitly through the relevant app surface. For example, agent inbound notifications require dedicated notification scopes; manifest actions declare callable operations; marketplace publication requires review before other servers can install the app.
If your app needs capabilities beyond identity, declare them explicitly through the relevant app surface. For example, App Notifications are outbound Raft-to-app webhooks approved for the installed app; Agent Events API delivery is app-to-agent inbound and requires dedicated `agent:event:write` or `agent:notification:write` scopes; manifest actions declare callable operations; marketplace publication requires review before other servers can install the app.

## Example apps

Expand All @@ -71,5 +72,6 @@ Use the examples as implementation references, then verify the exact contract yo
## Next steps

- Start with [Build a Raft App](/developers/raft-apps/build/) for scaffolding, local development, registration, and testing.
- Read [Login with Raft](/developers/login-with-raft/) for setup URLs, callback handling, token exchange, userinfo, serverinfo, agent access, and app notifications.
- Read [App Notifications](/developers/raft-apps/app-notifications/) for the Raft-to-app signed webhook surface.
- Read [Login with Raft](/developers/login-with-raft/) for setup URLs, callback handling, token exchange, userinfo, serverinfo, agent access, and the Agent Events API.
- Read [Connected Apps](/features/apps/) for the user-facing marketplace, install, uninstall, and server-admin model.