.agents/skills/project-create-topology/how-tos/verify-network-connections-layout-tokens.md
How can a developer verify that a local Cloud-connected Netdata Agent serves
topology:network-connections with the expected v1 link layout tokens and
correlation rule wiring, without exposing Cloud tokens, agent bearers, node ids,
machine GUIDs, claim ids, cookies, or raw endpoint rows?
This is a producer-contract validation recipe. It belongs to the developer topology skill, not to the public/operator query skills.
http://127.0.0.1:19999; set AGENT_URL when
using a non-default address.NETDATA_CLOUD_TOKEN and NETDATA_CLOUD_HOSTNAME in <repo>/.env.topology:network-connections.Capture the local identity tuple in memory and print only presence checks:
AGENT_URL="${AGENT_URL:-http://127.0.0.1:19999}"
AGENT_URL="${AGENT_URL%/}"
AGENT_HOST="${AGENT_URL#http://}"
AGENT_HOST="${AGENT_HOST#https://}"
AGENT_HOST="${AGENT_HOST%%/*}"
AGENT_SCHEME="http"
case "$AGENT_URL" in
https://*) AGENT_SCHEME="https" ;;
esac
AGENT_ORIGIN="${AGENT_SCHEME}://${AGENT_HOST}"
INFO_JSON="$(curl --fail -sS --max-time 10 "${AGENT_ORIGIN}/api/v3/info")"
jq '{
agent_count: (.agents | length),
node_id_present: ((.agents[0].nd // "") | length > 0),
machine_guid_present: ((.agents[0].mg // "") | length > 0),
claim_id_present: ((.agents[0].cloud.claim_id // "") | length > 0),
cloud_status: .agents[0].cloud.status
}' <<<"$INFO_JSON"
Load the token-safe direct-agent wrappers:
source docs/netdata-ai/skills/query-netdata-agents/scripts/_lib.sh
agents_load_env
Query the topology Function through the direct-agent path. Store the
raw response only under .local/:
NODE_UUID="$(jq -r '.agents[0].nd' <<<"$INFO_JSON")"
MACHINE_GUID="$(jq -r '.agents[0].mg' <<<"$INFO_JSON")"
FUNCTION_NAME="topology:network-connections"
FUNCTION_ENCODED="$(printf '%s' "$FUNCTION_NAME" | jq -sRr @uri)"
REQUEST_BODY='{"selections":{"group_by":["process_name"],"__topology_mode":["aggregated"],"sockets":["inbound","outbound","listening"],"protocols":["ipv4_tcp","ipv6_tcp","ipv4_udp","ipv6_udp"],"endpoints":["by_ip"]}}'
OUT="$(agents_audit_dir)/network-connections-aggregated-live.json"
agents_query_agent \
--node "$NODE_UUID" \
--host "$AGENT_HOST" \
--machine-guid "$MACHINE_GUID" \
POST "/api/v3/function?function=${FUNCTION_ENCODED}&timeout=120000&last=200" \
"$REQUEST_BODY" \
> "$OUT"
Print a sanitized response summary:
jq '{
status,
type,
schema_version: .data.schema_version,
actor_rows: .data.actors.rows,
link_rows: .data.links.rows,
correlation_point_rows: .data.correlation.points.rows,
correlation_claim_rows: .data.correlation.claims.rows
}' "$OUT"
Verify the producer's link layout tokens:
jq '.data.types.link_types
| with_entries({
key: .key,
value: {
label: .value.presentation.label,
color_slot: .value.presentation.color_slot,
line_style: .value.presentation.line_style,
width: .value.presentation.width,
variable: .value.presentation.variable,
layout: .value.presentation.layout
}
})' "$OUT"
Verify correlation rule wiring without printing endpoint rows:
jq '.data.correlation.rules
| with_entries({
key: .key,
value: {
action: .value.action,
priority: .value.priority,
key_space: .value.key_space,
point_actor_types: .value.point_actor_types,
claim_actor_types: .value.claim_actor_types,
correlation_link_types: .value.correlation_link_types,
output_link_type: .value.output_link_type
}
})' "$OUT"
Count graph links by type from the compact table:
jq -r '
.data as $d
| def col($table; $name):
($table.columns | map(.id) | index($name)) as $i
| $table.values[$i];
def v($c; $i):
if $c.codec == "const" then $c.value
elif $c.codec == "values" then $c.values[$i]
elif $c.codec == "dict" then $c.values[$c.indexes[$i]]
else null end;
(col($d.links; "type")) as $typeCol
| (col($d.links; "socket_count")) as $socketCol
| [range(0; $d.links.rows)
| {type: v($typeCol; .), socket_count: (v($socketCol; .) // 0)}]
| group_by(.type)
| map({type: .[0].type, links: length, sockets: (map(.socket_count) | add)})
| sort_by(.type)
| .[]
| [.type, .links, .sockets]
| @tsv
' "$OUT"
For the current network-connections v1 contract, expect these link types:
endpoint_socket: visible unresolved endpoint links, weakest
strength, normal distance.correlated_socket: Cloud aggregator output after exact absorption,
weakest strength, farthest distance.socket: local/resolved process links, stronger strength, farther
distance, variable width by socket_count.ownership: graph-coherence node-to-process links, dotted/faded,
normal strength, normal distance.The socket_exact correlation rule should consume endpoint_socket
through correlation_link_types and emit correlated_socket through
output_link_type.
.local/; it may contain
hostnames, private addresses, and process names.endpoint_socket with normal distance. That is a frontend force-layout
issue, not proof that the backend emitted farthest.