Agentic Workflow Platform Quickstart
The goal of this page is not to exhaust every concept, but to get you, by the shortest path, to confirm four things:
- whether the starter is wired successfully
- whether
/flowgram/tasks/*is actually exposed - whether a minimal no-LLM flow can run end to end
- whether a flow with an LLM can complete the full
validate -> run -> result -> reportchain
1. First, be clear about what this page verifies
The quickstart verifies that "the backend runtime is usable", not that "the frontend canvas is already wired in".
So the most reliable way to start is:
- Run the backend demo directly first
- Use HTTP requests to verify the task API first
- Confirm the two minimal chains: no-LLM and with-LLM
- Only then wire up the frontend canvas
This separates problems into:
- wiring problems
- schema problems
- model service problems
- frontend/backend integration problems
2. Shortest startup path: run the demo directly
If all you want is to confirm the runtime can run, the fastest way is not to scaffold a new project yourself but to run the demo that lives in the repo.
Dependent modules:
ai4j-flowgram-demoai4j-flowgram-spring-boot-starter
Startup command:
$env:ZHIPU_API_KEY="your-key"
cmd /c "mvn -pl ai4j-flowgram-demo -am -DskipTests package"
java -jar ai4j-flowgram-demo/target/ai4j-flowgram-demo-2.1.0.jar
Default service address:
- Port:
18080 - API root path:
/flowgram
3. Read the demo's default model configuration carefully first
This is the easiest place to stumble, because the demo defines two services at once, but the default value points at only one of them.
ai4j-flowgram-demo/src/main/resources/application.yml currently configures:
minimax-codingglm-coding
But the default is:
ai4j.flowgram.default-service-id = minimax-coding
This means:
- a no-LLM flow does not depend on any model key
- an LLM flow, if it does not explicitly specify a
serviceId, will default tominimax-coding
So if you have only configured ZHIPU_API_KEY but not MINIMAX_API_KEY, the two safest options are:
- Temporarily change
default-service-idin the demo configuration toglm-coding - Or explicitly pass
serviceId = glm-codinginside the LLM node
Filling in only modelName is not enough, because:
modelNamedecides which model to useserviceId/default-service-iddecides which registered service to route through
4. First confirm the endpoint is actually up
You do not need to write a complex workflow first; just check whether validate can respond.
Minimal request:
$body = @{
schema = @{
nodes = @()
edges = @()
}
inputs = @{}
} | ConvertTo-Json -Depth 5
Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:18080/flowgram/tasks/validate" -ContentType "application/json" -Body $body
If the runtime has been wired successfully, you will get back a structured validation error, not a 404.
What this step verifies:
FlowGramTaskControlleris mountedFlowGramRuntimeFacadeis availableFlowGramProtocolAdaptercan accept the schema DTO
5. Run a minimal no-LLM flow
The first one to try is always Start -> End, because it bypasses model service issues entirely and only exercises the task chain and schema.
$body = @{
schema = @{
nodes = @(
@{
id = "start_0"
type = "Start"
name = "start_0"
data = @{
outputs = @{
type = "object"
required = @("message")
properties = @{
message = @{ type = "string" }
}
}
}
},
@{
id = "end_0"
type = "End"
name = "end_0"
data = @{
inputs = @{
type = "object"
required = @("result")
properties = @{
result = @{ type = "string" }
}
}
inputsValues = @{
result = @{
type = "ref"
content = @("start_0", "message")
}
}
}
}
)
edges = @(
@{
sourceNodeID = "start_0"
targetNodeID = "end_0"
}
)
}
inputs = @{
message = "hello-flowgram"
}
} | ConvertTo-Json -Depth 10
$validate = Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:18080/flowgram/tasks/validate" -ContentType "application/json" -Body $body
$run = Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:18080/flowgram/tasks/run" -ContentType "application/json" -Body $body
Why this step matters
If this chain runs, it proves at least the following are real:
- the root graph structure is valid
Start/Endsemantics are normalREFreference resolution is normal- asynchronous task submission is normal
resultcollection is normal
6. Poll for the result; do not assume synchronous completion
run returns a taskId, not the final output.
You can poll the result using the same approach as the integration tests:
function Wait-FlowgramResult {
param(
[string]$TaskId,
[int]$TimeoutMs = 5000
)
$deadline = (Get-Date).AddMilliseconds($TimeoutMs)
while ((Get-Date) -lt $deadline) {
$result = Invoke-RestMethod -Method Get -Uri ("http://127.0.0.1:18080/flowgram/tasks/" + $TaskId + "/result")
if ($result.terminated) {
return $result
}
Start-Sleep -Milliseconds 100
}
throw "Timed out waiting for Flowgram result: $TaskId"
}
$result = Wait-FlowgramResult -TaskId $run.taskId
$report = Invoke-RestMethod -Method Get -Uri ("http://127.0.0.1:18080/flowgram/tasks/" + $run.taskId + "/report")
This is the correct way to consume it, because Flowgram's default model is an asynchronous task, not a synchronous RPC.
7. Now run a minimal LLM flow
Once the no-LLM flow runs, validate the model node.
Here it is recommended to pass serviceId explicitly, to avoid being misled by the demo default.
$body = @{
schema = @{
nodes = @(
@{
id = "start_0"
type = "Start"
name = "start_0"
data = @{
outputs = @{
type = "object"
required = @("message")
properties = @{
message = @{ type = "string" }
}
}
}
},
@{
id = "llm_0"
type = "LLM"
name = "llm_0"
data = @{
inputs = @{
type = "object"
required = @("serviceId", "modelName", "prompt")
properties = @{
serviceId = @{ type = "string" }
modelName = @{ type = "string" }
prompt = @{ type = "string" }
}
}
outputs = @{
type = "object"
required = @("result")
properties = @{
result = @{ type = "string" }
}
}
inputsValues = @{
serviceId = @{
type = "constant"
content = "glm-coding"
}
modelName = @{
type = "constant"
content = "glm-4.7"
}
prompt = @{
type = "ref"
content = @("start_0", "message")
}
}
}
},
@{
id = "end_0"
type = "End"
name = "end_0"
data = @{
inputs = @{
type = "object"
required = @("result")
properties = @{
result = @{ type = "string" }
}
}
inputsValues = @{
result = @{
type = "ref"
content = @("llm_0", "result")
}
}
}
}
)
edges = @(
@{ sourceNodeID = "start_0"; targetNodeID = "llm_0" }
@{ sourceNodeID = "llm_0"; targetNodeID = "end_0" }
)
}
inputs = @{
message = "Please answer with exactly three words: FlowGram spring boot."
}
} | ConvertTo-Json -Depth 12
$validate = Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:18080/flowgram/tasks/validate" -ContentType "application/json" -Body $body
$run = Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:18080/flowgram/tasks/run" -ContentType "application/json" -Body $body
$result = Wait-FlowgramResult -TaskId $run.taskId
$report = Invoke-RestMethod -Method Get -Uri ("http://127.0.0.1:18080/flowgram/tasks/" + $run.taskId + "/report")
8. What you should check closely in the LLM flow
Do not only look at "whether there is a result"; look at these points:
- whether
result.statusissuccess - whether
result.result.resulthas the final text - whether
report.nodes.llm_0.outputs.metricscarries token metrics - whether
report.trace.summary.metricsis aggregated correctly
This simultaneously verifies:
RegistryBackedFlowGramModelClientResolverAi4jFlowGramLlmNodeRunner- trace metrics backfill
FlowGramTraceViewprojection
9. If it fails, troubleshoot in this order
9.1 validate fails outright
Check first:
- whether there is exactly one
Start - whether there is at least one
End - whether the
inputsValuesreference paths are correct - whether the node type is recognized by the backend
9.2 The no-LLM flow runs, but the LLM flow fails
Check first:
- whether
serviceIdpoints to a registered service - whether
default-service-idmatches the provider key you prepared - whether
modelNameis a model the service supports - whether the corresponding provider key actually exists
9.3 run succeeds but you never get a terminated result
Check first:
- whether you are polling
result - whether the node executor is stuck
- whether an external service is timing out
10. From the demo to your own project
Once you have verified the following four things, you should leave the demo and move into your own project:
validatecan return a structured validation resultStart -> Endruns reliably- the
LLMnode runs reliably - the way to read
report/result/traceis already clear
Recommended further reading: