Check-Graph
tman
provides the check graph
command to validate predefined graphs or a start_graph
command for correctness. To see the usage details, use the following command:
$ tman check graph -h
Check whether the graph content of the predefined graph or start_graph command is correct. For more detailed usage, run 'graph -h'
Usage: tman check graph [OPTIONS] --app <APP>
Options:
--app <APP>
The absolute path of the app defined in the graph. By default, the predefined graph will be read from the first one in the list.
--predefined-graph-name <PREDEFINED_GRAPH_NAME>
Specify a predefined graph name to check, otherwise, all predefined graphs will be checked.
--graph <GRAPH>
Specify the JSON string of a 'start_graph' command to be checked. If not specified, the predefined graph in the first app will be checked.
-h, --help
Print help
The check graph
command is designed to handle graphs that may span multiple apps, so it does not require being run from the root directory of a specific app. Instead, it can be executed from any directory, with the --app
parameter used to specify the folders of the apps involved in the graph.
Example Usages
Check all predefined graphs in
property.json
:tman check graph --app /home/TEN-Agent/agents
Check a specific predefined graph:
tman check graph --predefined-graph-name va.openai.azure --app /home/TEN-Agent/agents
Check a
start_graph
command:tman check graph --graph '{ "type": "start_graph", "seq_id": "55", "nodes": [ { "type": "extension", "name": "test_extension", "addon": "basic_hello_world_2__test_extension", "extension_group": "test_extension_group", "app": "msgpack://127.0.0.1:8001/" }, { "type": "extension", "name": "test_extension", "addon": "basic_hello_world_1__test_extension", "extension_group": "test_extension_group", "app": "msgpack://127.0.0.1:8001/" } ] }' --app /home/TEN-Agent/agents
Prerequisites
Predefined Graph Definition Requirement: If a predefined graph name is specified, the definition will be extracted from the
property.json
file of the app specified by the first--app
parameter.Package Installation Requirement: Before running the
check graph
command, all extensions that the app depends on must be installed using thetman install
command. This is necessary because the validation process requires information about each extension in the graph, such as APIs defined in theirmanifest.json
files.Unique App URI Requirement: In a multi-app graph, each app's
property.json
must define a unique_ten::uri
. Additionally, theuri
value cannot be set to"localhost"
.
Validation Rules
1. Presence of Nodes
The nodes
array is required in any graph definition. If absent, an error will be thrown.
Example (No nodes defined):
tman check graph --graph '{ "type": "start_graph", "seq_id": "55", "nodes": [] }' --app /home/TEN-Agent/agents
Output:
Checking graph[0]... ❌. Details: No extension node is defined in graph. All is done. ❌ Error: 1/1 graphs failed.
2. Uniqueness of Nodes
Each node in the nodes
array represents a specific extension instance within a group of an app, created by a specified addon. Therefore, each extension instance should be uniquely represented by a single node. A node must be uniquely identified by the combination of app
, extension_group
, and name
. Multiple entries for the same extension instance are not allowed.
Example (Duplicate nodes):
tman check graph --graph '{ "type": "start_graph", "seq_id": "55", "nodes": [ { "type": "extension", "name": "test_extension", "addon": "basic_hello_world_2__test_extension", "extension_group": "test_extension_group", "app": "msgpack://127.0.0.1:8001/" }, { "type": "extension", "name": "test_extension", "addon": "basic_hello_world_1__test_extension", "extension_group": "test_extension_group", "app": "msgpack://127.0.0.1:8001/" } ] }' --app /home/TEN-Agent/agents
Output:
Checking graph[0]... ❌. Details: Duplicated extension was found in nodes[1], addon: basic_hello_world_1__test_extension, name: test_extension. All is done. ❌ Error: 1/1 graphs failed.
3. Extensions used in connections should be defined in nodes
All extension instances referenced in the connections
field, whether as a source or destination, must be explicitly defined in the nodes
field. Any instance not defined in the nodes
array will cause validation errors.
Example (Source extension not defined):
Imagine that the content of
property.json
of a TEN app is as follows.{ "_ten": { "predefined_graphs": [ { "name": "default", "auto_start": false, "nodes": [ { "type": "extension", "name": "some_extension", "addon": "default_extension_go", "extension_group": "some_group" } ], "connections": [ { "extension": "some_extension", "cmd": [ { "name": "hello", "dest": [ { "extension": "some_extension" } ] } ] } ] } ] } }
tman check graph --app /home/TEN-Agent/agents
Output:
Checking graph[0]... ❌. Details: The extension declared in connections[0] is not defined in nodes, extension_group: producer, extension: some_extension. All is done. ❌ Error: 1/1 graphs failed.
Example (Destination extension not defined):
Imagine that the content of
property.json
of a TEN app is as follows.{ "_ten": { "predefined_graphs": [ { "name": "default", "auto_start": false, "nodes": [ { "type": "extension", "name": "some_extension", "addon": "default_extension_go", "extension_group": "some_group" }, { "type": "extension", "name": "some_extension_1", "addon": "default_extension_go", "extension_group": "some_group" } ], "connections": [ { "extension": "some_extension", "cmd": [ { "name": "hello", "dest": [ { "extension": "some_extension_1" } ] }, { "name": "world", "dest": [ { "extension": "some_extension_1" }, { "extension": "consumer" } ] } ] } ] } ] } }
tman check graph --app /home/TEN-Agent/agents
Output:
Checking graph[0]... ❌. Details: The extension declared in connections[0].cmd[1] is not defined in nodes extension_group: some_group, extension: consumer. All is done. ❌ Error: 1/1 graphs failed.
4. The addons declared in the nodes
must be installed in the app
nodes
must be installed in the appExample (The
_ten::uri
in property.json is not equal to theapp
field in nodes):Imagine that the content of property.json of a TEN app is as follows.
{ "_ten": { "predefined_graphs": [ { "name": "default", "auto_start": false, "nodes": [ { "type": "extension", "name": "some_extension", "addon": "default_extension_go", "extension_group": "some_group" } ] } ], "uri": "http://localhost:8001" } }
tman check graph --app /home/TEN-Agent/agents
Output:
Checking graph[0]... ❌. Details: The following packages are declared in nodes but not installed: [("localhost", Extension, "default_extension_go")]. All is done. ❌ Error: 1/1 graphs failed.
The problem is all packages in the app will be stored in a map which key is the
uri
of the app, and each node in the graph is retrieved by theapp
field (which islocalhost
by default). Theapp
in node (i.e., localhost) is mismatch with theuri
of app (i.e., http://localhost:8001).Example (the ten_packages does not exist as the
tman install
has not executed):Imagine that the content of property.json of a TEN app is as follows.
{ "_ten": { "predefined_graphs": [ { "name": "default", "auto_start": false, "nodes": [ { "type": "extension", "name": "some_extension", "addon": "default_extension_go", "extension_group": "some_group" } ] } ] } }
And the
ten_packages
directory does _NOT exist.tman check graph --app /home/TEN-Agent/agents
Output:
Checking graph[0]... ❌. Details: The following packages are declared in nodes but not installed: [("localhost", Extension, "default_extension_go")]. All is done. ❌ Error: 1/1 graphs failed.
5. In connections, messages sent from one extension should be defined in the same section
Example:
Imagine that all the packages have been installed.
tman check graph --graph '{ "nodes": [ { "type": "extension", "name": "some_extension", "addon": "default_extension_go", "extension_group": "some_group" }, { "type": "extension", "name": "another_ext", "addon": "default_extension_go", "extension_group": "some_group" } ], "connections": [ { "extension": "some_extension", "cmd": [ { "name": "hello", "dest": [ { "extension": "another_ext" } ] } ] }, { "extension": "some_extension", "cmd": [ { "name": "hello_2", "dest": [ { "extension": "another_ext" } ] } ] } ] }' --app /home/TEN-Agent/agents
Output:
Checking graph[0]... ❌. Details: extension 'some_extension' is defined in connection[0] and connection[1], merge them into one section. All is done. ❌ Error: 1/1 graphs failed.
6. In connections, the messages sent out from one extension should have a unique name in each type
Example:
Imagine that all the packages have been installed.
tman check graph --graph '{ "nodes": [ { "type": "extension", "name": "some_extension", "addon": "addon_a", "extension_group": "some_group" }, { "type": "extension", "name": "another_ext", "addon": "addon_b", "extension_group": "some_group" } ], "connections": [ { "extension": "some_extension", "cmd": [ { "name": "hello", "dest": [ { "extension": "another_ext" } ] }, { "name": "hello", "dest": [ { "extension": "some_extension" } ] } ] } ] }' --app /home/TEN-Agent/agents
Output:
Checking graph[0]... ❌. Details: - connection[0]: - Merge the following cmd into one section: 'hello' is defined in flow[0] and flow[1]. All is done. ❌ Error: 1/1 graphs failed.
7. The messages declared in the connections should be compatible
The message declared in each message flow in the connections will be checked if the schema is compatible, according to the schema definition in the manifest.json of extensions. The rules of message compatible are as follows.
If the message schema is not found neither in the source extension nor the target extension, the message is compatible.
If the message schema is only found in one of the extensions, the message is incompatible.
The message is compatible only if the following conditions are met.
The property type is compatible.
If the property is an object, the fields both in the source and target schema must have a compatible type.
If the
required
keyword is defined in the target schema, there must be arequired
keyword in the source schema, which is the superset of therequired
in the target.
Example:
Imagine that all the packages have been installed.
The content of manifest.json in
addon_a
is as follows.{ "type": "extension", "name": "addon_a", "version": "0.1.0", "dependencies": [ { "type": "system", "name": "ten_runtime_go", "version": "0.1.0" } ], "package": { "include": ["**"] }, "api": { "cmd_out": [ { "name": "cmd_1", "property": { "foo": { "type": "string" } } } ] } }
And, the content of manifest.json in
addon_b
is as follows.{ "type": "extension", "name": "addon_b", "version": "0.1.0", "dependencies": [ { "type": "system", "name": "ten_runtime_go", "version": "0.1.0" } ], "package": { "include": ["**"] }, "api": { "cmd_in": [ { "name": "cmd_1", "property": { "foo": { "type": "int8" } } } ] } }
Checking graph with the following command.
tman check graph --graph '{ "nodes": [ { "type": "extension", "name": "some_extension", "addon": "addon_a", "extension_group": "some_group" }, { "type": "extension", "name": "another_ext", "addon": "addon_b", "extension_group": "some_group" } ], "connections": [ { "extension": "some_extension", "cmd": [ { "name": "cmd_1", "dest": [ { "extension": "another_ext" } ] } ] } ] }' --app /home/TEN-Agent/agents
Output:
Checking graph[0]... ❌. Details: - connections[0]: - cmd[0]: Schema incompatible to [extension_group: some_group, extension: another_ext], { .foo: type is incompatible, source is [string], but target is [int8] } All is done. ❌ Error: 1/1 graphs failed.
8. The app
in node must be unambiguous
app
in node must be unambiguousThe app
field in each node must met the following rules.
The
app
field must be equal to the_ten::uri
of the corresponding TEN app.Either all nodes should have
app
declared, or none should.The
app
field can not belocalhost
.The
app
field can not be an empty string.Example (some of the nodes specified the
app
field):Checking graph with the following command.
tman check graph --graph '{ "nodes": [ { "type": "extension", "name": "some_extension", "addon": "addon_a", "extension_group": "some_group" }, { "type": "extension", "name": "another_ext", "addon": "addon_b", "extension_group": "some_group", "app": "http://localhost:8000" } ] }' --app /home/TEN-Agent/agents
Output:
❌ Error: The graph json string is invalid Caused by: Either all nodes should have 'app' declared, or none should, but not a mix of both.
Example (No
app
specified in all nodes, but some source extension specifiedapp
in the connections):Checking graph with the following command.
tman check graph --graph '{ "nodes": [ { "type": "extension", "name": "some_extension", "addon": "addon_a", "extension_group": "some_group" }, { "type": "extension", "name": "another_ext", "addon": "addon_b", "extension_group": "some_group" } ], "connections": [ { "extension": "some_extension", "app": "http://localhost:8000", "cmd": [ { "name": "cmd_1", "dest": [ { "extension": "another_ext" } ] } ] } ] }' --app /home/TEN-Agent/agents
Output:
❌ Error: The graph json string is invalid Caused by: connections[0].the 'app' should not be declared, as not any node has declared it
Example (No
app
specified in all nodes, but some target extension specifiedapp
in the connections):Checking graph with the following command.
tman check graph --graph '{ "nodes": [ { "type": "extension", "name": "some_extension", "addon": "addon_a", "extension_group": "some_group" }, { "type": "extension", "name": "another_ext", "addon": "addon_b", "extension_group": "some_group" } ], "connections": [ { "extension": "some_extension", "cmd": [ { "name": "cmd_1", "dest": [ { "extension": "another_ext", "app": "http://localhost:8000" } ] } ] } ] }' --app /home/TEN-Agent/agents
Output:
❌ Error: The graph json string is invalid Caused by: connections[0].cmd[0].dest[0]: the 'app' should not be declared, as not any node has declared it
Example (The
app
field in nodes is not equal to the_ten::uri
of app):Same as Rule 4.
Example (The
app
field islocalhost
in a single-app graph):Checking graph with the following command.
tman check graph --graph '{ "nodes": [ { "type": "extension", "name": "some_extension", "addon": "addon_a", "extension_group": "some_group" }, { "type": "extension", "name": "another_ext", "addon": "addon_b", "extension_group": "some_group", "app": "localhost" } ], "connections": [ { "extension": "some_extension", "cmd": [ { "name": "cmd_1", "dest": [ { "extension": "another_ext" } ] } ] } ] }' --app /home/TEN-Agent/agents
Output:
❌ Error: Failed to parse graph string, nodes[1]: 'localhost' is not allowed in graph definition, and the graph seems to be a single-app graph, just remove the 'app' field
Example (The
app
field islocalhost
in a multi-app graph):Checking graph with the following command.
tman check graph --graph '{ "nodes": [ { "type": "extension", "name": "some_extension", "addon": "addon_a", "extension_group": "some_group", "app": "http://localhost:8000" }, { "type": "extension", "name": "another_ext", "addon": "addon_b", "extension_group": "some_group", "app": "localhost" } ], "connections": [ { "extension": "some_extension", "app": "http://localhost:8000", "cmd": [ { "name": "cmd_1", "dest": [ { "extension": "another_ext" } ] } ] } ] }' --app /home/TEN-Agent/agents
Output:
❌ Error: Failed to parse graph string, nodes[1]: 'localhost' is not allowed in graph definition, change the content of 'app' field to be consistent with '_ten::uri'
Last updated
Was this helpful?