Quickstart
1. Sign in at the app
Section titled “1. Sign in at the app”Create an account.
2. Add an inference option
Section titled “2. Add an inference option”Connect and configure an Openrouter key and model.
3. Install the SDK
Section titled “3. Install the SDK”bun/npm/pnpm add @canopyhq/sdk zod4. Declare a tool
Section titled “4. Declare a tool”This is the schema and metadata that will be presented for the tenant to consent to; separate from the execution definition.
import * as z from "zod";import { Canopy, appdoc, bind, declare, propose, type Bindings } from "@canopyhq/sdk";
const tools = { refund: declare({ description: "refund a payment", input: z.object({ amount: z.int(), customer: z.string() }), output: z.object({ refunded: z.int() }), }),};5. Derive the document
Section titled “5. Derive the document”Combine tool metadata and application-wide metadata into an Application Document which will be presented to tenant for consent.
const document = appdoc({ name: "payhq", description: "moves money" }, tools);6. Propose and Consent
Section titled “6. Propose and Consent”Propose the composed Application Document, then store the retrieved key upon consent.
const proposal = await propose(document);console.log("consent at", proposal.consentUrl);
const { key } = await proposal.granted();7. Bind and open
Section titled “7. Bind and open”Define executors for tools and open a session.
const refunds = (ledger: Ledger): Bindings<typeof tools> => bind(tools, { refund: async ({ amount, customer }) => ({ refunded: await ledger.refund(customer, amount) }),});
const canopy = new Canopy({ key });const session = await canopy.open({ principal: "user:aiden", instructions: "Help customers with their payments.", tools: refunds(ledger),});8. Send one message
Section titled “8. Send one message”Await a single turn and close the session.
const turn = await session.send("refund c-9 five dollars");console.log(turn.reply, turn.finish);await session.close();9. Read the tail
Section titled “9. Read the tail”Read the first twenty events of the session.
for await (const record of session.records({ from: 0, to: 20 })) { console.log(record);}