Skip to content

Introduction

Zupflow is the backend for adding AI agents to your product. Each agent works inside one of your customers’ workspaces, for one person or a whole team, with access to that customer’s own connected accounts (their task tracker, their CRM, their docs) and nothing else.

Your product talks to Zupflow with an API key and receives webhooks. Your customers connect their accounts on Zupflow's hosted page. Zupflow calls their apps' MCP servers and your organization's model providers. YOUR PRODUCTYour customerYour appwhere people use agentsYour backendholds the API keyZupflowWorkspacesone per customerConnecthosted account sign-inAgentsinstructions + toolsRunsdurable, step by stepApprovalsa person decidesWebhookssigned and retriedTool policySealed credentialsAudit logSandboxProductionconnects accounts, onceREST APIwebhooksTHEIR APPS · MCPLinearNotionGitHubHubSpotMODEL PROVIDERS · YOUR KEYSOpenAIAnthropicOpenRoutertool callsmodel turns
Your backend drives Zupflow over its API and hears back through webhooks. Your customers only see your product, and Zupflow's hosted Connect page once per account.

Putting agents in a multi-tenant product means solving the same hard problems every time. Zupflow solves them once, behind one HTTP API.

You build

  • The experience: where people talk to agents, in your UI
  • Which agents exist and what each one is for
  • How you ask a person to approve a sensitive call
  • What happens with a run’s result

Zupflow handles

  • Isolating every customer’s data, credentials and runs
  • OAuth sign-in to each service, with tokens sealed and refreshed
  • Deciding every tool call: allow, ask a person, or deny
  • Runs that survive restarts and never send a call twice
  • Signed, retried webhooks and a full audit log

Everything in Zupflow is one of a few objects, and each lives in exactly one scope. Every ID carries its object’s prefix, so run_034HXHH2LZFzvoaSAhfGVD is always a run.

Organizationorg_your company
Apps app_Tool policyModel connections mcn_Members
Sandboxenvironment
API keys key_Webhook endpoints we_
Workspacews_one per customer of yours
Installationinst_a connected account
granted to
Agentagt_instructions + model
starts
Runrun_events and tool calls
Productionenvironment

The same objects, kept apart. Nothing falls back from one environment to the other.

Each object lives in exactly one scope. One customer's workspace never reaches another's.
Object ID prefix What it is
Workspace ws_ One of your customers, tied to your own ID for them (external_id).
App app_ An MCP server your customers can connect, such as Linear or Notion.
Installation inst_ One customer’s connected account for an app, with its credentials sealed.
Agent agt_ Instructions and a model, with grants to named tools of installations.
Run run_ One piece of work an agent does from an input, recorded event by event.
Tool call call_ One call a run asks for, allowed, waiting for approval, or denied.
Webhook endpoint we_ A URL of yours that receives signed events.
API key key_ Your backend’s credential, for one environment of one organization.
flowchart LR
I([Your backend<br/>starts a run]) --> M[Model turn<br/>with granted tools]
M -->|asks for a tool| D{Policy decides}
D -->|allow| S[Call sent<br/>to the app]
D -->|needs approval| A[Run waits<br/>webhook to you]
A -->|a person allows| S
D -->|deny| M
S --> M
M -->|final answer| C([Completed<br/>webhook to you])

Every step is saved before the next one starts, so a run picks up where it left off after any interruption. How it works follows a request end to end.

Every organization has a Sandbox and a Production environment. A workspace belongs to one, fixed when it’s created, and configuration never falls back from one to the other. API keys are per environment too (zf_test_… and zf_live_…).

The API, the SDK and everything on these pages are the same wherever Zupflow runs. Zupflow is also open source, so you can run the whole platform yourself: see Self-hosting.