Networks
A network is a saved graph of agent, tool, router, verification, and approval nodes that runs as a single unit. Each network has a stable network_id and a version that is bumped every time you save; older versions are retained so a run can record exactly which one it executed.
Networks are stored in the deployment's vault. Retrieve one by id (optionally pinning a version), overwrite it with a new save, duplicate it under a fresh id, or delete it. Executing a network starts a run and returns its identifier; follow its progress by reading the run record and its node outputs.
All of these endpoints require an access token. Send it as a bearer token, or rely on the session cookie forwarded by the same-origin /networks-api proxy.
- GET /networks List networks
- GET /networks/{network_id} Retrieve a network
- POST /networks Create or update a network
- POST /networks/{network_id}/duplicate Duplicate a network
- POST /networks/{network_id}/save-as-template Save a network as a template
- POST /networks/{network_id}/execute Execute a network
- DEL /networks/{network_id} Delete a network
Paths are relative to /networks-api
The network object
A saved network specification.
Attributes
-
network_idstringStable identifier for the network. Opaque; do not parse it.
-
versionstringVersion string in
major.minorform (for example1.2). Incremented on each save unlessbump=none. -
namestringHuman-readable name.
-
descriptionnullable stringFree-text description of what the network does.
-
domain_idstringThe domain the network runs under. Supplies routing hints and policy preferences at execution time.
-
modestringexecuteruns the graph;plan_onlyproduces a plan without carrying it out.Possible values-
execute -
plan_only
-
-
created_bystringHow the network was authored.
Possible values-
manual -
intent-layer -
plan-agent
-
-
created_atnullable stringCreation timestamp, ISO 8601 with an explicit offset.
-
updated_atnullable stringLast-saved timestamp, ISO 8601 with an explicit offset.
-
user_local_calendar_datenullable stringCalendar date at creation in the caller's timezone, stamped once so runs resolve relative dates consistently.
-
user_timezonenullable stringIANA timezone the calendar date was resolved in; falls back to
UTCwhen none was supplied. -
configobjectExecution and governance settings for the whole network.
Show child attributes Hide child attributes
-
evaluation_enabledbooleanWhether node outputs are scored against their evaluation configuration.
-
evaluation_thresholdnumberScore in
0–1a run must reach to be marked as passing. -
memory_hints_enabledbooleanWhether the run is indexed into the memory graph so related runs and hints can be produced.
-
auto_apply_hintsbooleanWhether accepted hints are applied automatically.
-
learning_enabledbooleanWhether routing and tool-selection learning observes this network's runs.
-
max_agentic_roundsintegerUpper bound on tool-calling rounds for an agentic node (
1–12). -
network_repair_enabledbooleanWhether a failed run may attempt an automatic repair cycle.
-
max_network_repair_cyclesintegerMaximum repair cycles per run (
0–3).
-
-
nodesarray of objectsThe graph's nodes.
Show child attributes Hide child attributes
-
node_idstringUnique within the network.
-
typestringThe node's kind.
Possible values-
LLMAgent -
ToolCall -
Router -
Aggregator -
SubNetwork -
Verification -
HumanApproval
-
-
labelnullable stringDisplay name for the step, used wherever the node is shown.
-
sourcestringWhere the node came from.
agent_hubnodes requireagent_hub_id.Possible values-
agent_hub -
manual -
auto_generated
-
-
agent_hub_idnullable stringThe bound Agent Hub agent, when
sourceisagent_hub. -
model_routingobjectHow a model is chosen for an LLM-backed node.
Show child attributes Hide child attributes
-
strategystringSelection strategy.
pinnedrequirespinned_model.Possible values-
auto -
pinned -
capability -
energy -
regulated
-
-
pinned_modelnullable stringModel id to use when
strategyispinned. -
required_capabilitynullable stringCapability the chosen model must have (for example
tool_use,reasoning,analysis). -
fallback_modelsarray of stringsOrdered model ids tried after the primary candidate fails.
-
-
toolsarray of stringsTool ids the node may call.
-
tool_idnullable stringThe tool a
ToolCallnode runs. -
network_refnullable stringThe network a
SubNetworknode executes. -
use_agentic_loopbooleanWhether an
LLMAgentnode runs an iterative tool-calling loop rather than a single call.
-
-
edgesarray of objectsDirected connections between nodes.
Show child attributes Hide child attributes
-
fromstringSource node id.
-
tostringTarget node id.
-
typestringEdge kind.
conditionalrequirescondition;subnetworkrequiresnetwork_ref.Possible values-
sequential -
parallel -
conditional -
subnetwork
-
-
conditionnullable stringExpression evaluated to decide whether a
conditionaledge is taken. -
network_refnullable stringReferenced network for a
subnetworkedge.
-
-
toolsarray of stringsNetwork-level tool ids available to nodes.
{
"network_id": "support-triage",
"version": "1.2",
"name": "Support triage",
"description": "Classify an inbound ticket and draft a reply.",
"domain_id": "customer-success",
"mode": "execute",
"created_by": "intent-layer",
"created_at": "2026-09-01T09:30:00Z",
"updated_at": "2026-09-01T09:30:00Z",
"user_local_calendar_date": "2026-09-01",
"user_timezone": "Europe/London",
"config": {
"evaluation_enabled": true,
"evaluation_threshold": 0.75,
"memory_hints_enabled": true,
"auto_apply_hints": false,
"learning_enabled": false,
"max_agentic_rounds": 5,
"network_repair_enabled": true,
"max_network_repair_cycles": 1
},
"nodes": [
{
"node_id": "classify",
"type": "LLMAgent",
"label": "Classify the ticket",
"source": "manual",
"agent_hub_id": null,
"model_routing": {
"strategy": "auto",
"pinned_model": null,
"required_capability": "analysis",
"fallback_models": []
},
"tools": [],
"tool_id": null,
"network_ref": null,
"use_agentic_loop": false
},
{
"node_id": "draft_reply",
"type": "LLMAgent",
"label": "Draft a reply",
"source": "manual",
"agent_hub_id": null,
"model_routing": {
"strategy": "auto",
"pinned_model": null,
"required_capability": "analysis",
"fallback_models": []
},
"tools": [],
"tool_id": null,
"network_ref": null,
"use_agentic_loop": false
}
],
"edges": [
{
"from": "classify",
"to": "draft_reply",
"type": "sequential",
"condition": null,
"network_ref": null
}
],
"tools": []
} List networks
GET /networks-api/networks
Returns the identifiers of every saved network.
Returns a plain array of network_id strings. Retrieve any one with Retrieve a network.
- Authentication
- Bearer token How it works
Parameters
No parameters.
Returns
Returns an array of network identifiers.
curl "$VDF_BASE_URL/networks-api/networks" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" const response = await fetch(`${process.env.VDF_BASE_URL}/networks-api/networks`, {
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.get(
f"{os.environ['VDF_BASE_URL']}/networks-api/networks",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
timeout=30,
)
response.raise_for_status()
data = response.json() [
"support-triage",
"weekly-report",
"invoice-reconciler"
] Retrieve a network
GET /networks-api/networks/{network_id}
Retrieves a saved network specification.
Returns the network object. By default the current version is returned; pass version to retrieve a specific saved version.
- Authentication
- Bearer token How it works
Path parameters
-
network_idstring RequiredThe network's identifier.
Query parameters
-
versionstringA specific version to retrieve. Defaults to the current version.
Returns
Returns the network object.
Errors
- 404 No network with this identifier (or version) exists.
curl "$VDF_BASE_URL/networks-api/networks/support-triage" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" const response = await fetch(`${process.env.VDF_BASE_URL}/networks-api/networks/support-triage`, {
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.get(
f"{os.environ['VDF_BASE_URL']}/networks-api/networks/support-triage",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"network_id": "support-triage",
"version": "1.2",
"name": "Support triage",
"description": "Classify an inbound ticket and draft a reply.",
"domain_id": "customer-success",
"mode": "execute",
"created_by": "intent-layer",
"created_at": "2026-09-01T09:30:00Z",
"updated_at": "2026-09-01T09:30:00Z",
"config": {
"evaluation_enabled": true,
"evaluation_threshold": 0.75,
"memory_hints_enabled": true,
"auto_apply_hints": false,
"learning_enabled": false,
"max_agentic_rounds": 5,
"network_repair_enabled": true,
"max_network_repair_cycles": 1
},
"nodes": [
{
"node_id": "classify",
"type": "LLMAgent",
"label": "Classify the ticket",
"source": "manual",
"model_routing": {
"strategy": "auto",
"required_capability": "analysis",
"fallback_models": []
},
"tools": []
}
],
"edges": [],
"tools": []
} Create or update a network
POST /networks-api/networks
Saves a network, creating it or overwriting the existing one.
Saves a network specification. If a network with the same network_id already exists, its version is bumped and the new specification becomes the current version; otherwise the network is created.
By default the minor version is incremented. Pass bump=major for a major increment or bump=none to overwrite the current version in place. network_id, name, and domain_id are required in the body.
Any SubNetwork node whose network_ref does not yet exist has a placeholder network created for it so execution cannot fail on a missing reference; when that happens the response carries a warnings array naming each placeholder.
Set the X-Client-Timezone header (or a client_timezone body field) to record the calendar context the network was created in.
- Authentication
- Bearer token How it works
Headers
-
X-Client-TimezonestringIANA timezone used to stamp the network's calendar context when it is not already set.
Query parameters
-
bumpstringHow to change the version on save.
Possible values-
none -
minor -
major
-
Body parameters application/json
-
network_idstring RequiredIdentifier to save under.
-
namestring RequiredHuman-readable name.
-
domain_idstring RequiredDomain the network runs under.
-
descriptionstringFree-text description.
-
versionstringIgnored on save; the stored version is derived from the current one and
bump. -
modestringExecution mode.
Possible values-
execute -
plan_only
-
-
configobjectExecution and governance settings; see the network object.
-
nodesarray of objectsGraph nodes; see the network object.
-
edgesarray of objectsGraph edges; see the network object.
-
toolsarray of stringsNetwork-level tool ids.
Returns
Returns the saved network object, with a warnings array when placeholder subnetworks were created.
curl -X POST "$VDF_BASE_URL/networks-api/networks?bump=minor" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"network_id": "support-triage",
"name": "Support triage",
"domain_id": "customer-success",
"description": "Classify an inbound ticket and draft a reply.",
"mode": "execute",
"nodes": [
{
"node_id": "classify",
"type": "LLMAgent",
"label": "Classify the ticket",
"source": "manual"
}
],
"edges": [],
"tools": []
}' const response = await fetch(`${process.env.VDF_BASE_URL}/networks-api/networks?bump=minor`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
network_id: 'support-triage',
name: 'Support triage',
domain_id: 'customer-success',
description: 'Classify an inbound ticket and draft a reply.',
mode: 'execute',
nodes: [
{
node_id: 'classify',
type: 'LLMAgent',
label: 'Classify the ticket',
source: 'manual',
},
],
edges: [],
tools: [],
}),
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.post(
f"{os.environ['VDF_BASE_URL']}/networks-api/networks",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
params={
"bump": "minor",
},
json={
"network_id": "support-triage",
"name": "Support triage",
"domain_id": "customer-success",
"description": "Classify an inbound ticket and draft a reply.",
"mode": "execute",
"nodes": [
{
"node_id": "classify",
"type": "LLMAgent",
"label": "Classify the ticket",
"source": "manual",
},
],
"edges": [],
"tools": [],
},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"network_id": "support-triage",
"version": "1.3",
"name": "Support triage",
"description": "Classify an inbound ticket and draft a reply.",
"domain_id": "customer-success",
"mode": "execute",
"created_by": "manual",
"created_at": "2026-09-01T09:30:00Z",
"updated_at": "2026-09-02T11:05:00Z",
"config": {
"evaluation_enabled": true,
"evaluation_threshold": 0.75,
"learning_enabled": false
},
"nodes": [
{
"node_id": "classify",
"type": "LLMAgent",
"label": "Classify the ticket",
"source": "manual",
"model_routing": {
"strategy": "auto",
"required_capability": "analysis"
},
"tools": []
}
],
"edges": [],
"tools": []
} Duplicate a network
POST /networks-api/networks/{network_id}/duplicate
Copies the current version of a network into a new network at version 1.0. Supply network_id in the body to choose the new identifier; omit it and one is derived from the source (for example support-triage-copy). Supply name to set the copy's name, or the source name with (Copy) appended is used.
- Authentication
- Bearer token How it works
Path parameters
-
network_idstring RequiredThe network to copy.
Headers
-
X-Client-TimezonestringIANA timezone used to stamp the copy's calendar context.
Body parameters application/json
-
network_idstringIdentifier for the copy. Must differ from the source. Auto-derived when omitted.
-
namestringName for the copy.
-
client_timezonestringIANA timezone for the copy's calendar context.
Returns
Returns the new network object.
Errors
- 400 The target identifier equals the source identifier.
- 404 The source network does not exist.
- 409 A network with the target identifier already exists.
curl -X POST "$VDF_BASE_URL/networks-api/networks/support-triage/duplicate" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"network_id": "support-triage-eu",
"name": "Support triage (EU)"
}' const response = await fetch(`${process.env.VDF_BASE_URL}/networks-api/networks/support-triage/duplicate`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
network_id: 'support-triage-eu',
name: 'Support triage (EU)',
}),
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.post(
f"{os.environ['VDF_BASE_URL']}/networks-api/networks/support-triage/duplicate",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
json={
"network_id": "support-triage-eu",
"name": "Support triage (EU)",
},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"network_id": "support-triage-eu",
"version": "1.0",
"name": "Support triage (EU)",
"domain_id": "customer-success",
"mode": "execute",
"created_by": "intent-layer",
"created_at": "2026-09-02T11:10:00Z",
"updated_at": "2026-09-02T11:10:00Z",
"nodes": [],
"edges": [],
"tools": []
} Save a network as a template
POST /networks-api/networks/{network_id}/save-as-template
Publishes a saved network as a reusable intent template.
Converts a saved network into an intent template that renders a fresh network per request, so it can be picked in the template picker and run through Render a template and run it.
The conversion replaces the identity fields (network_id, domain_id, and by default description) with placeholders, drops per-task planning state, and writes node types and routing strategies explicitly. Any other placeholder found in the network (for example inside a prompt) is rejected.
By default the template is saved to your private layer, visible only to you. Saving to the shared layer that every user can see (scope: system) is reserved for your administrator.
The response includes warnings with portability notes — private subnetwork references, tool arguments copied verbatim from the source, and agent bindings — that do not block a private save but may need review before the template is shared.
- Authentication
- Bearer token How it works
- Permission
- Saving to the shared layer (
scope: "system") requires an administrator account; any signed-in user may save a private template.
Path parameters
-
network_idstring RequiredThe network to publish.
Body parameters application/json
-
template_idstring RequiredIdentifier for the new template. Must match
^[A-Za-z0-9_-]{1,128}$. -
namestringNetwork name inside the template. Defaults to the source network's name.
-
descriptionstringNetwork description inside the template. Defaults to a placeholder carrying each run's task text.
-
task_classesarray of stringsTask classes the intent layer may auto-route to this template. Empty means the template runs only when picked explicitly; unknown values are rejected.
Possible values-
github_repo_planning -
github_repo_understanding -
document_review -
web_research -
generic
-
-
domain_idsarray of stringsRouting hint. Defaults to the network's domain.
-
workspace_slugsarray of stringsWorkspaces the template is offered in.
-
scopestringLayer to save to.
user(the default for regular callers) is your private layer;systemis the shared layer and requires administrator rights.Possible values-
system -
user
-
-
versionstringWhich saved version to convert. Defaults to the current version.
Returns
Returns the created template's identifier and layer, the source network id and version, portability warnings, and the generated template content.
Errors
- 404 The network or the requested version does not exist.
- 422 The identifier is invalid, a task class is unknown, or the network contains a placeholder that cannot be converted.
- 409 A template with this identifier already exists.
curl -X POST "$VDF_BASE_URL/networks-api/networks/support-triage/save-as-template" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"template_id": "support-triage-template",
"name": "Support triage",
"task_classes": [
"generic"
]
}' const response = await fetch(`${process.env.VDF_BASE_URL}/networks-api/networks/support-triage/save-as-template`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
template_id: 'support-triage-template',
name: 'Support triage',
task_classes: ['generic'],
}),
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.post(
f"{os.environ['VDF_BASE_URL']}/networks-api/networks/support-triage/save-as-template",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
json={
"template_id": "support-triage-template",
"name": "Support triage",
"task_classes": ["generic"],
},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"status": "created",
"template_id": "support-triage-template",
"scope": "user",
"owner_user_id": "42",
"is_private": true,
"network_id": "support-triage",
"network_version": "1.2",
"warnings": [],
"content": "template_id: support-triage-template\nrenderer: static_spec\n..."
} Execute a network
POST /networks-api/networks/{network_id}/execute
Starts a run of a saved network and returns its identifier.
Loads the current version of the network, opens a run, and starts executing it in the background. The response returns immediately with the run_id and a started status.
The request body is the run input. Common fields are input (or task_description) for the task text and conversation_context to carry prior chat turns; every other field is forwarded to the run as input and made available to nodes.
Follow the run's progress by reading its status and node outputs with Retrieve a run.
- Authentication
- Bearer token How it works
Path parameters
-
network_idstring RequiredThe network to run.
Headers
-
X-Client-TimezonestringIANA timezone used to resolve relative dates in the run.
Body parameters application/json
-
inputstringThe task text for the run.
task_descriptionis accepted as an alias. -
conversation_contextobjectPrior chat turns and the original goal, used to give the run follow-up context.
Returns
Returns the new run's identifier and a started status.
Errors
- 404 The network does not exist.
curl -X POST "$VDF_BASE_URL/networks-api/networks/support-triage/execute" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"input": "Classify ticket 4471 and draft a reply."
}' const response = await fetch(`${process.env.VDF_BASE_URL}/networks-api/networks/support-triage/execute`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
input: 'Classify ticket 4471 and draft a reply.',
}),
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.post(
f"{os.environ['VDF_BASE_URL']}/networks-api/networks/support-triage/execute",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
json={
"input": "Classify ticket 4471 and draft a reply.",
},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"run_id": "run-20260901-093000-a1b2c3",
"status": "started"
} Delete a network
DEL /networks-api/networks/{network_id}
Deletes a network and all of its versions.
Permanently deletes the network and every saved version. Runs already recorded against it are not removed.
- Authentication
- Bearer token How it works
Path parameters
-
network_idstring RequiredThe network to delete.
Returns
Returns the deleted identifier and a deleted status.
Errors
- 404 The network does not exist.
curl -X DELETE "$VDF_BASE_URL/networks-api/networks/support-triage-eu" \
-H "Authorization: Bearer $VDF_ACCESS_TOKEN" const response = await fetch(`${process.env.VDF_BASE_URL}/networks-api/networks/support-triage-eu`, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.VDF_ACCESS_TOKEN}`,
},
});
if (!response.ok) throw new Error(`Request failed with status ${response.status}`);
const data = await response.json(); import os
import requests
response = requests.delete(
f"{os.environ['VDF_BASE_URL']}/networks-api/networks/support-triage-eu",
headers={"Authorization": f"Bearer {os.environ['VDF_ACCESS_TOKEN']}"},
timeout=30,
)
response.raise_for_status()
data = response.json() {
"status": "deleted",
"network_id": "support-triage-eu"
}