Project Networks
Declare private connectivity boundaries, expose selected project interfaces, and identify outbound consumers that need a tailnet route.
What it is. A named, provider-neutral private connectivity boundary for a project. A project can declare multiple networks, and each network can later bind to a Swirls-managed or customer-owned tailnet.
Use it when customers need to reach a Swirls app, form, webhook, MCP channel, or database without publishing it to the public internet—or when a Swirls workflow or agent must call an on-prem or tailnet-only service.
Project Networks separate two decisions:
- The
networkblock owns what Swirls exposes into that private network. - Each outbound consumer chooses the network it reaches through with
network: <name>.
Declare a network
network corporate {
label: "Corporate network"
description: "Private operations and internal systems"
expose: {
apps: [operations]
channels: [support_mcp]
forms: [employee_intake]
webhooks: [internal_events]
databases: [
{
database: crm
connections: [application, analytics]
}
]
}
}label, description, and the entire expose block are optional. An empty network is useful when the project only needs outbound access.
| Exposure | What the name refers to |
|---|---|
apps | Top-level app blocks |
channels | mcp, web, or swirls channel blocks with a Swirls-hosted interface |
forms | Top-level form blocks |
webhooks | Top-level webhook blocks |
databases | A managed database plus the exact nested named connections to expose |
services | Reserved for the service primitive; currently rejected by validation |
Database exposure is connection-granular on purpose. The network does not expose a database merely because the database exists; you must select the exact named credentials intended for that boundary.
Reach private services
Set network: on the consumer that owns the destination:
node fetch_customer {
type: http
url: "https://crm.internal/api/customer"
network: corporate
}
mcp operations_tools {
url: "https://mcp.internal/mcp"
auth: static
network: corporate
}
postgres warehouse {
connection: WAREHOUSE_DATABASE_URL
network: corporate
table events {
schema: @json { { "type": "object" } }
}
}Self-managed connection blocks also accept network: when they declare base_url: and auth:. Managed OAuth connections do not: their provider transport remains Swirls-managed.
A network-aware HTTP node must use a static absolute http or https URL. A dynamic @ts URL is rejected because Swirls must know the destination before it selects a private route.
Cloud inventory and bindings
After deployment, the project's Networks page shows every named declaration, the interfaces it exposes, and the outbound resources that consume it. This makes the private connectivity contract reviewable before infrastructure is attached.
Named tailnet bindings and live execution gateways are the next control-plane milestone. Until a network is bound, network-aware consumers fail closed with an explicit error and never fall back to the public internet.
Multiple networks
Declare as many networks as the project needs. For example, corporate might connect employee systems while customer_acme reaches a customer's tailnet. An interface or consumer is attached only where it is named, which keeps boundaries explicit in source review.
Related
- Connections: OAuth and self-managed API credential slots
- MCP servers: Remote tools agents consume
- Postgres: Existing databases a workflow queries
- Managed databases: Databases Swirls provisions, including named connections
Actions and the catalog
Typed provider operations installed with swirls add. Browse the integration catalog, install action blocks, generate them from any API spec, and request new providers.
Access
Declare who can run what. role blocks derive roles from verified identity attributes, and policy grants map those roles to agents, workflows, and tools.