PTENES
Skip to content
MODULE 1.3

🧭 How to move through a graph

A static graph is useless. This module is the toolbox: how to traverse it, find the cheapest path, know what runs before what, how many can run in parallel, and how not to get stuck in a cycle. All of this comes up again identical in Track 4, with agents in place of nodes.

6
Topics
40
Minutes
Basic
Level
Practical
Type
Progress in this module
0%0 of 6
1

🚶 Choose: breadth-first or depth-first traversal

Traverse (or “traversing”) and visiting the nodes of a graph by following its edges. There are two basic ways to do this, and choosing between them isn’t a technical detail: it’s a strategic decision you’ll repeat with agents.

🆕 New here? BFS and DFS

  • BFS (breadth-first search, breadth-first search): visits all the neighbors of a node before going deeper. Imagine exploring a building one floor at a time.
  • DFS (depth-first search, depth-first search): chooses a path and follows it to the end before returning and trying another. Imagine walking down a hallway to the last door before turning back.
BREADTH (BFS) — level by level 1 2 3 4 5 6 DEPTH (DFS) — corridor to the end 1 2 5 3 4 6

What to look at: e o same a graph of both sides — only the order of the numbers changes. In breadth, 4 and 5 only appear after the entire second level. In depth, 3 and 4 appear before the right branch is even touched. Neither is “better”: breadth finds the closest one first, depth finds a fast response.

✓ Breadth works when

  • ✓You want the closest / shortest (degrees of separation)
  • ✓It’s better to scan many options superficially than to dive deep into one
  • ✓With agents: “give me 8 different approaches, without going into depth”

✓ Depth works when

  • ✓Any valid solution will do, and you want to get there quickly
  • ✓The path only makes sense as a whole (you can’t evaluate it halfway through)
  • ✓With agents: “pursue this hypothesis all the way before switching”

⚠️ The rule that prevents it from getting stuck

Mark which nodes have already been visited. Without that, any cycle turns your traversal into an infinite loop—the algorithm keeps going back and forth between the same two nodes forever. It’s bug number 1 for anyone who writes a traversal by hand.

Key concepts

BFS

One step at a time

DFS

Corridor to the end

Visited

Without marking it, the cycle gets stuck

Becomes a strategy

Breadth or depth, with agents

2

🛣️ Find the cheap path (not the shortest one)

“Shortest path” almost always means lowest total weight, not fewer hops. Those are different things, and confusing them costs money. A path with 2 expensive edges can be worse than one with 5 cheap edges.

In the morning routine from the previous module, this became obvious: the shortcut had fewer in nodes and also cost less. But change the weight to “risk” and the picture flips — the shortcut may be the shortest path and the most dangerous at the same time. The weight you choose defines what is “best.”

1

Choose the weight before optimizing

Tokens? Latency? Risk? Confidence? Each choice produces a different optimal route. Optimizing without stating the weights is optimizing in the dark.

2

Weight can change during execution

An API’s latency rises, a model gets congested, prices change. An optimal route calculated once becomes a guess after a while.

3

More than one weight at the same time

When you want something cheap e reliable, there is no “the” best — only trade-offs. And then you’re already at the problem Track 2 calls “one metric is never enough.”

Key concepts

Short ≠ cheap

Count weight, not hops

The weight defines the optimum

Declare it in advance

Dynamic weight

Routes age

Multi-weight

Turns into a trade-off, not an optimum

3

📋 Discover the topological order

Topological order is a valid execution order in a DAG: nothing appears before anything it depends on. That's what the make calculates, which is what your CI calculates — and what your agent graph orchestrator will calculate.

🎯 Two practical consequences

  • •There isn't just one order. Several queues may be valid. That’s good: it means there’s flexibility—and that flexibility is exactly where parallelism can happen.
  • •If you can't order them, there's a cycle. The algorithm gets stuck, and that’s a diagnosis, not a bug: it just showed you a circular dependency you hadn’t noticed.

🧪 Practical example: order your graph and detect cycles

Objective: given a dependency graph, get the execution order — and receive a clear error if there’s a cycle. Paste it into the browser console (F12) or run it in Node.

// grafo: no -> lista de quem DEPENDE dele (roda depois)
const dep = {
  "pesquisar": ["escrever"],
  "escrever":  ["revisar"],
  "coletar_dados": ["escrever"],
  "revisar":   []
};

function ordenar(g) {
  const grau = {}, saida = [];
  Object.keys(g).forEach(n => grau[n] = 0);
  Object.values(g).flat().forEach(n => grau[n] = (grau[n] || 0) + 1);
  let prontos = Object.keys(grau).filter(n => grau[n] === 0);

  while (prontos.length) {
    console.log("rodam em PARALELO agora:", prontos.join(", "));
    const proximos = [];
    for (const n of prontos) {
      saida.push(n);
      for (const viz of (g[n] || [])) if (--grau[viz] === 0) proximos.push(viz);
    }
    prontos = proximos;
  }
  if (saida.length !== Object.keys(grau).length)
    throw new Error("CICLO detectado — nao existe ordem valida");
  return saida;
}

console.log("ordem final:", ordenar(dep).join(" → "));

How to verify: the first line should say rodam em PARALELO agora: pesquisar, coletar_dados — the two without dependencies. Then escrever, then revisar. Now force a cycle: add "revisar": ["pesquisar"] and run it again — it should trigger the CYCLE error. If it does, you just implemented circular dependency detection.

Switch: the names by <as etapas do seu processo>. The lines that “RUN IN PARALLEL” are your allocation plan.

Key concepts

Valid queue

No one before your dependency

It's not the only one

Several orderings work

In-degree

Zero = ready to run

Failure = cycle

Diagnosis, not a bug

4

⚡ Count the Actual Parallelism

The previous script already printed the answer: each line “run in PARALLEL now” is a level of the graph, and the size of that line is how many workers fit at that point. This applies equally to people and agents. Launching 20 agents in a graph that only allows 3 nodes at a time doesn’t speed anything up—it just wastes resources.

level 1 — 2 fit level 2 — 3 fit level 3 — fits 1 (bottleneck) A B C D E join the width of each level = how many agents make sense at that moment

What to look at: the three bands have different widths — 2, 3, and 1. The last level (“combine”) is a bottleneck: no matter how many agents you have, only one passes through there at a time. This pattern—branching into several, then narrowing to one—is the fan-out / fan-in that Track 4 will name.

Key concepts

Level

Who’s ready at the same time

Breadth

Worker cap

Bottleneck

Width level 1

Fan-out / fan-in

Splits, then joins

5

🌀 Escape the cycle: limits, progress, human oversight

A cycle isn't a defect — it's what lets you repeat work until it's good. The defect is a cycle no output. There are exactly three types of output, and every cycle you draw needs at least one of them written beside it.

✓ Legitimate outputs

  • ✓Cap: “at most 5 rounds”—crude, but it always stops
  • ✓Progress criterion: “if two consecutive rounds don’t improve, give up”
  • ✓Human: “after N rounds, ask someone”

✗ False outputs

  • ✗“It stops when it’s good”—who decides what’s good?
  • ✗“The model knows when to stop”—it doesn’t, and the bill comes due
  • ✗Mutual deadlock: A waits for B, B waits for A, and no one moves

💡 Practical tip

Use all three together, in layers: progress criteria as the output normal, a ceiling as a safety net, and a human as the final authority. The ceiling alone is wasteful (it runs 5 times even when 2 would do); the criterion alone is risky (if the measurement breaks, it never triggers).

Key concepts

A cycle is useful

Repeat until it works

Cap

Safety net

Progress

Normal output

Deadlock

Mutual waiting brings everything to a halt

6

🔍 Write it in JSON: the format the orchestrator reads

In practice, a graph is a dictionary: for each node, the list of neighbors. This is called adjacency list and handles 95% of cases. The trick for agents is simple: in addition to the neighbors, store the node data — model, tools, prompt, cost limit. That’s what turns an ordinary graph into an agentic graph agentic.

🧪 Practical example: the skeleton you'll reuse through the end of the course

Objective: have a file grafo.json that describes nodes (with agent config) and edges (with conditions). Save as grafo.json in your project folder.

{
  "nos": {
    "pesquisar": {
      "papel": "Levanta fontes sobre <o tema> e resume em notas curtas",
      "modelo": "<modelo rapido e barato>",
      "ferramentas": ["busca_web", "ler_url"],
      "teto_custo_usd": 0.50
    },
    "escrever": {
      "papel": "Escreve o texto usando SO as notas recebidas",
      "modelo": "<modelo bom de escrita>",
      "ferramentas": [],
      "teto_custo_usd": 1.00
    },
    "revisar": {
      "papel": "Confere fatos e clareza. Responde aprovado: true|false",
      "modelo": "<modelo forte de raciocinio>",
      "ferramentas": ["busca_web"],
      "contexto_limpo": true,
      "teto_custo_usd": 1.00
    }
  },
  "arestas": [
    { "de": "pesquisar", "para": "escrever", "quando": "sempre",  "passa": "notas" },
    { "de": "escrever",  "para": "revisar",  "quando": "sempre",  "passa": "rascunho" },
    { "de": "revisar",   "para": "escrever", "quando": "aprovado == false", "passa": "criticas",
      "max_voltas": 2 },
    { "de": "revisar",   "para": "FIM",      "quando": "aprovado == true" }
  ]
}

How to verify: four checks, all visual — (1) the JSON is valid (paste it into any validator or run JSON.parse); (2) there is at least a edge with quando different from "sempre" — otherwise you wrote a queue, not a graph; (3) every back edge has max_voltas — and it’s the stopping condition from topic 5; (4) there is a path to "FIM". If any of the four is missing, the graph has a real defect.

Switch: everything between < >. Save this file—the course's Track 5 will turn it into code you can run.

Quick check: Your topological sorting algorithm stalls and can't produce the sequence. What does that mean?

Key concepts

Adjacency list

Node → neighbors

Data in the node

Model, tools, ceiling

Condition on the edge

Without it, it’s just a queue

No framework

JSON is enough to get started

📌 Module Summary

✓
Breadth x depth — scan shallowly or pursue deeply; always mark visited nodes.
✓
Short ≠ cheap — the weight you choose defines what “better” means.
✓
Topological order — the execution queue; if it fails, you’ve found a cycle.
✓
Level breadth = real parallelism — and the bottleneck is a width-1 level.
✓
Every cycle needs an exit — a limit, progress criterion, and human oversight, in layers.
✓
JSON is enough — node with agent config + edge with condition = agentic graph.

Next track:

Track 2 — Loop Engineering: the anatomy of the cycle, why the verifier is the bottleneck, and the four structural ways a loop can betray you.