Build your first Active Knowledge Graph¶
At a glance
- You'll build — a tiny service that returns a message, then enhance it to echo its input, then deploy it and call it over REST. No application code, only a graph model.
- You'll use — the MiniGraph Playground (the interactive workbench) and one skill,
graph.data.mapper.- Prerequisites — the app running with
app.env=devand the Playground open in a browser; about 10 minutes. New to the idea? Read Knowledge Graph as Application first.- Conventions — lines you type into the Playground inbox are shown in code blocks; the console's reply follows under
>.
Step 1 — a root and an end¶
Every graph has a Root (entry) and an End (exit). Create the root first:
Now create the end node and give it a skill — graph.data.mapper — so it actually does
something. The mapping[] entry copies the constant hello world into output.body, the
response payload:
create node end
with type End
with properties
skill=graph.data.mapper
mapping[]=text(hello world) -> output.body
Connect them so traversal can flow root → end (the label, here done, names the connection):
Run it. instantiate graph creates a runnable instance from the model; run traverses it:
The console shows the traversal and the result:
> run
Walk to root
Walk to end
Executed end with skill graph.data.mapper in 1.7 ms
{
"output": {
"body": "hello world"
}
}
Graph traversal completed in 9 ms
That is a complete, working Active Knowledge Graph: a root, an active node carrying a skill, and an end — behavior expressed entirely as a model.
Step 2 — make it echo the input¶
A real service reacts to input. Update the end node to map the request body to the response body instead of a constant:
update node end
with type End
with properties
skill=graph.data.mapper
mapping[]=input.body -> output.body
This time, dry-run with mock input — instantiate graph accepts seed values, here putting the
constant it works into input.body.message:
> run
Walk to root
Walk to end
Executed end with skill graph.data.mapper in 0.4 ms
{
"output": {
"body": {
"message": "it works"
}
}
}
Graph traversal completed in 2 ms
A dry-run needs no live dependencies — it's how you validate a model before deploying it.
Step 3 — export the model¶
Export the graph to JSON so it can be deployed. The engine writes it to the temp graph location
(location.graph.temp, default file:/tmp/graph) and stamps the graph's name onto the root node:
> export graph as my-first-graph
Added name=my-first-graph to Root node
Graph exported to /tmp/graph/my-first-graph.json
Step 4 — deploy it¶
Deployment is a file copy plus a manifest entry. The relevant application.properties keys:
# temp working location (must be file:/ — read/write)
location.graph.temp=file:/tmp/graph
# the graph manifest - the quality gate and the only door to deployed execution
graph.model.automation=classpath:/graphs.yaml
Copy the model into the deployed-graph folder and list its ID in the manifest
(graphs.yaml), then restart the app:
Like flows.yaml, the manifest carries the location of its own models: the optional
location entry points at the deployed-graph folder (file:/ or classpath:/ — it is
read-only) and defaults to classpath:/graph, so most projects can omit it.
At startup, CompileGraph validates every manifest graph once — structure, the root node's
purpose, data-mapping syntax, and the suspend/resume contract — and only graphs that pass
become executable. A graph that fails the gate, or is not listed, answers HTTP-404 as if
it does not exist, exactly like an invalid flow under CompileFlows. The startup log tells
you why a graph was rejected (Rejected graph <id> - <reason>).
Step 5 — call it over REST¶
A deployed graph is reachable at the generic endpoint POST /api/graph/{graph-id}, where the id is
the name you exported. Send it some input:
curl -X POST http://127.0.0.1:8085/api/graph/my-first-graph \
-H "Content-Type: application/json" \
-d '{"message": "it is a wonderful day"}'
(The port follows your app's configuration; 8085 is illustrative.)
What just happened¶
The graph isn't called directly — it's wrapped by an Event Script flow, which is how it gets a REST endpoint without coupling execution to the protocol:
http.flow.adapterreceivesPOST /api/graph/my-first-graphand runs thegraph-executorflow.graph.executorbuilds a graph instance and traverses root → end.- At the end node it invokes
graph.data.mapper, which writesoutput.body. async.http.responsereturns that body to yourcurl.
You can see exactly these steps in the application's telemetry log.
What's next¶
You built behavior with one skill. The graph becomes genuinely active when nodes decide, compute, and fetch:
graph.math— inline math andIF/THEN/ELSEbranching for decisions.graph.api.fetcher— call external APIs declaratively via data-dictionary and provider nodes.graph.extension— delegate to a sub-graph or an Event Script flow.graph.task— invoke a composable function through its route name.
Each of these gets a worked example in the built-in skills reference.
See also¶
- Knowledge Graph as Application — the concepts behind what you just built.
- Event Script Syntax — the data-mapping syntax the skills share, and the flow layer that exposes graphs over REST.