A connection is one vendor account you have given Graft. It has three parts: an auth scheme (how the proxy presents the credential to the vendor), a credential (what the proxy injects), and a host set (the hosts the credential may be sent to, and nothing else). It belongs to you, not to an agent: GitHub is entered once however many harnesses you run. Credentials are write-only after entry. The console shows when a credential was set and never what it is.

Where the credential lives

Every connection comes from a provider, which decides how you connect the vendor and what happens to a call. The keyring is every deployment’s provider and covers every vendor: you enter the secret in the console, Graft stores it encrypted, and the proxy injects it. On Graft Cloud a second provider stands in front of it for the vendors Pipedream Connect offers, Gmail first: you connect with one click, Pipedream holds the vendor’s token, and every call is relayed through Pipedream’s proxy, which adds the token on the way. Graft then stores no credential for the connection at all, only the id of the account at Pipedream. The card says which provider a connection came through; a connection with no badge is the keyring’s.

The scheme

The scheme decides which secret fields the form asks for and how the proxy carries the credential. A connection made through Pipedream records relay as its scheme (a connection through your own API gateway records gateway): not something you choose, but how its calls leave, relayed rather than signed. Some schemes carry non-secret parameters beside the credential: a header name and an optional prefix, a query parameter name, a token URL and scopes, an authorize URL. The agent proposes these from the vendor’s documentation; you can edit them on the form.

The host set

The primary host is an https base URL that vendor-relative paths resolve against, https://api.github.com say. Additional hosts are hostnames a vendor’s API spans, for an SDK that reaches several. The primary’s own host is always in the set. Every host must be public. Private, loopback, link-local, cloud-metadata and internal addresses are refused when the agent proposes them, refused again as you type them on the form, and refused a third time by the proxy at call time, on the address the name actually resolved to. A credential is only ever sent to a public host. The proxy pins every call to this set. A request for a host outside it is refused, and a redirect is followed only within it, and only when the deployment has turned redirects on.

Scope

Scope is the connections one agent may use. It is edited on the agent’s page under Scope, saved whole with Save scope, and in effect on the agent’s next call. Scope is where the security property lives. The capability token minted for each run names the agent and the connections in its scope, so an authored tool running for one agent cannot reach a connection that agent was never given, whatever its code says. A connection reaches an agent’s scope two ways. When the agent proposes it with request_connection and you connect it in the console, it lands in that agent’s scope alone. A connection you add yourself under Connections → Add connection, or that another agent proposed, reaches an agent when you tick it in that agent’s Scope. Each connection in scope also gives the agent an execute__<connection id> tool, the low-level way to run code against that connection while a tool is being authored. acquire takes a connectionId and refuses one outside the agent’s scope, pointing at request_connection.

Tools bind to the vendor, not the connection

An authored tool is bound to a connection’s vendor slug (github), not to the connection row. That is what lets a revoked connection’s tools stay in the toolbox, awaiting reconnection, and ask again once a credential is re-entered.

Try it