Gmail, Slack user tokens, Notion and most Google APIs do not hand out API keys: you sign in at the vendor and consent, and the vendor issues tokens to a client somebody registered. Graft runs that flow against a client you register yourself. Graft operates no OAuth client of its own for these vendors.
On Graft Cloud, Gmail does not take this path. It connects with one click through Pipedream Connect, whose client is the one you sign in to, and the token stays with Pipedream. See One click on Graft Cloud. This page is for a vendor Pipedream does not cover, and for self-hosted Graft without a Pipedream project of its own.
The agent is the guide. It reads the vendor’s OAuth documentation, proposes the endpoints and scopes, and tells you what to create and where to paste the one value only Graft knows. The client secret and the tokens never pass through it; you enter the secret in the console and the consent runs in a popup there.

What the agent proposes

The agent calls request_connection with the scheme oauth_authorization_code and, from the vendor’s documentation, the Authorize URL, the Token URL and the Scopes the task needs, as narrow as the task allows. It leaves the client id out, because it cannot know it. The answer carries the handoff link and a redirectUri, and the agent relays both with three sentences: where to create the client, what to name it, and which redirect URI to paste.

Registering the client

1

Create an OAuth client at the vendor

In the vendor’s developer console, create an OAuth client of the web application kind. Name it with “Graft” in it, Graft (my laptop agent), so you recognise it in the vendor’s list a year from now.
2

Paste the redirect URI

The redirect URI is your Graft deployment’s origin plus /api/oauth/callback. The form shows it with a Copy button, fetched from the server so it is the exact URI the callback answers on. Paste it into the client’s authorized redirect URIs exactly; a character off and the vendor refuses the consent with redirect_uri_mismatch.
3

Enter the client on the form

Open the handoff link. The form is pre-filled with the agent’s proposal and asks for two things the agent could not know: the Client id, as a required parameter, and the Client secret, as the one secret. The redirect URI is shown beside them.
4

Connect

Connect stores the client and opens the vendor’s consent page in a popup. Complete the consent there. The form waits and says so; when the vendor sends the browser back, the tokens are stored encrypted, the card settles, and the agent’s waiting call answers connected. If the browser blocks the popup, the form offers a link to open the consent page yourself. Stop waiting returns the form to Connect if you change your mind; the client id and secret are kept.
Once connected, the proxy injects the access token on every call and refreshes it when it expires. Your tools call ctx.fetch as for any other scheme and never see a token.

Google

Google is the worked example the skill carries, and it has one wart.
  • A Google Cloud project starts in Testing mode. Add your own Google account under OAuth consent screen → Test users, or the consent page refuses you.
  • Create the client under APIs & Services → Credentials → Create credentials → OAuth client ID, type Web application, after enabling the API the scopes belong to (Gmail API for Gmail) under Library.
  • Gmail’s read scope is https://www.googleapis.com/auth/gmail.readonly; the host is gmail.googleapis.com; the endpoints are https://accounts.google.com/o/oauth2/v2/auth and https://oauth2.googleapis.com/token.
Whenever a host on the form is Google’s, the form shows this notice: A Google Cloud project in Testing mode issues refresh tokens that expire after seven days, so this connection will ask you to reconnect weekly; publishing the app removes that, but a published app that reads Gmail needs Google’s verification and a CASA assessment.

When a call fails later

A vendor 401 on an OAuth connection usually means the refresh token died: the seven-day expiry above, or you revoked the app at the vendor. Graft has already tried to refresh once and passed the vendor’s own 401 to the tool. The connection card then reads needs re-consent and offers Reconnect, which runs the consent again with the client secret still in place; nothing is typed, and no approval is touched. The agent can start this for you with request_credential. For an OAuth connection the card asks you to reconnect, not to type anything, unless the connection was revoked in the console, in which case you enter the client secret first and the consent follows.

The connection’s states

The card under Connections shows where an OAuth connection stands: awaiting client secret before the secret is entered, awaiting consent once it is and the consent has not completed (with Connect), needs re-consent after a refused refresh (with Reconnect), and connected, with when you consented and when the token was last refreshed. Tokens are never shown.

Try it