The Deterministic Core: Algorithms and Data Structures for Marketing Agents
A practical guide to the search, ranking, graph, deduplication, and memory operations around marketing agents, with the assumptions and limits that matter in production.
A practitioner’s guide to familiar computer science patterns in agent systems
A marketing agent that prepares a weekly report may call a model to explain what changed. Before that call, software has to retrieve the right records, remove duplicates, order dependent steps, and select which campaigns deserve attention. Afterward, it may need to validate and store the result. Those are ordinary engineering tasks, and their correctness depends on the shape of the data and the guarantees the system needs.
Here, “deterministic core” means the software operations around model judgment have explicit rules. It does not mean every result is exact or repeatable: approximate data structures, changing inputs, and remote services still introduce uncertainty. This guide follows six recurring operations: find, explore, order, deduplicate, route, and retain or reduce information. For each, ask what must be true about the input, what the operation guarantees, what it can lose, and how a failure will be detected. A familiar structure can make a system more predictable; it does not make the whole agent reliable or safe by itself.
This technical companion can be read when an implementation needs it; it is not a prerequisite for completing the reporting pilot. It sits alongside our guides to skills, agent architecture, tools and MCP, an OpenClaw marketing agent, maintenance and security, and portable plugins. Those pieces describe capabilities and workflows. Here we look at the data operations that support them.
Start with the Operation and Its Contract
A data structure arranges information so certain tasks are easier or faster. An algorithm is a set of steps for completing a task. A hash set, a type of exact membership list, can quickly check whether an item is present. A Bloom filter uses less memory to answer a similar question, but its answer is only a well-informed guess. Choose between them based on the task and the cost of being wrong.
Before selecting a pattern, write down:
- Input condition: Is the data sorted, complete, fresh, bounded, or trusted?
- Required result: Do you need an exact answer, a ranked subset, a valid sequence, or a plausible grouping?
- Failure cost: Can a missed record be retried, or could it trigger a duplicate spend or suppress a compliance issue?
- Operating limit: What are the volume, memory, latency, API, and review constraints?
- Evidence: How will you compare the implementation with a simpler baseline and detect drift?
These questions matter because some patterns below are exact only when their assumptions hold. Others trade certainty for speed or memory. Put any uncertainty at a boundary where the system can check it.
Find and Explore
Binary Search: Find a Boundary in Ordered Data
Binary search repeatedly cuts an ordered search space in half. It can find a value in a sorted collection, or find the first position where a condition changes from false to true. The number of checks grows slowly: even doubling the collection adds only one more check.
That second use has an important condition: all the false results must come before all the true results (a property called monotonicity). For example, if you sort campaigns by cost per acquisition, you can find the first value above a threshold. Daily cost per acquisition does not necessarily move in one direction. If it moves above and below a target, binary search can skip an earlier crossing or return a misleading boundary. Use a scan, a database query, or another method when the condition does not hold.
For a marketing tool, first check whether a database or language library already provides the ordered lookup. Binary search is useful when the data is actually ordered and the workload makes repeated lookups worth optimizing. It does not make unsorted data searchable with so few checks.
Breadth-First and Depth-First Search: Traverse a Graph
Breadth-first search (BFS) explores connections one step away at a time. In a network where each connection counts equally, it can find a route with the fewest connections. Depth-first search (DFS) follows one route as far as it can before going back to try another. Both can visit every reachable item efficiently if the system records which items it has already seen and stores, for each item, its direct connections. In computer science, this network of items and connections is called a graph.
A site crawler or repository scanner can use either. BFS may be useful when it should examine nearer pages first, such as links close to a start page. DFS may suit a deep hierarchy when following one branch at a time is convenient. Neither order guarantees business priority: high traffic, compliance importance, and limits on how quickly an API can be called need their own scheduling rules. A wide network can also require a large waiting list for BFS. A DFS that relies on nested function calls can exceed a programming language’s call-depth limit.
For ad accounts, first use the platform’s supported hierarchy and pagination. Traversal logic should record visited identifiers, handle inaccessible or changing nodes, and stop within explicit limits. A graph walk is not a substitute for access controls or a complete-data check.
KMP and Rabin-Karp: Match Known Text Patterns
Knuth-Morris-Pratt (KMP) and Rabin-Karp search for an exact sequence of characters inside longer text. KMP prepares the search phrase so it can avoid repeating checks. Rabin-Karp compares short numeric fingerprints of sections of text, updating each fingerprint as it moves along, then checks any likely match against the actual text. When searching for many phrases, a tool designed to find several at once may be a better fit than repeating the search for each phrase.
These methods can help find exact phrases, identifiers, URLs, or tracking parameters. They can flag a known phrase in ad copy for review. They cannot determine whether a claim is legally compliant, whether two passages mean the same thing, or whether arbitrary natural-language text contains an instruction intended to manipulate a model.
That limit matters for prompt injection. Known-string checks can catch known examples, but attackers can change wording, hide instructions in retrieved material, or use other formats. Pattern matching is one signal for screening and logging, not a security boundary. Treat retrieved text as untrusted, keep tool permissions narrow, validate outputs, and require approval where consequences warrant it. OWASP’s prompt-injection guidance describes the limits of input filtering and the importance of reducing impact.
Bloom Filter: An Approximate Membership Check
A Bloom filter is a compact memory-saving check that gives an approximate answer to “have we seen this item?” It can say “possibly present” for an item that was never added. This is called a false positive. A correctly maintained standard Bloom filter will not say “absent” for an item that was added. How often it gives a false positive depends on its size and how many items have been added; when it fills up, false positives become more common. Guava’s documentation explains this guarantee and the capacity assumptions behind it.
A crawler can use a Bloom filter to avoid checking its complete list of URLs on every step. If the filter says “definitely not present,” the crawler can proceed. If it says “possibly present,” check the complete list before skipping the URL. That list, rather than the approximate filter, decides whether the URL is a duplicate.
This extra check matters when a false positive could silently skip needed work. A Bloom filter is a memory-saving hint, not a record of what happened or the final authority on what is true. The system still needs clear rules for changes, deletions, restarts, outdated information, and repeated requests. For many marketing workflows, an exact list or a unique request identifier stored in a database (an idempotency key) is simpler and safer; the identifier lets the system recognize a request it has already handled.
Order and Select
Heap: Keep a Small Ranked Set
A heap is a way to organize items so the smallest or largest is quick to retrieve, without keeping the whole collection fully sorted. It is useful when records arrive over time but only the top K (top few, where K is the number you choose) are needed. For example, a min-heap of size K can keep the highest-scoring K items as each new item arrives, without sorting the entire collection again.
A reporting job might use this for the five campaigns with the highest qualified-conversion rate. Define the metric, time window, minimum volume, and tie rule first. If each campaign appears in several incoming batches, merge by campaign identifier before ranking; otherwise the heap may select multiple rows for one campaign. A heap maintains rank under the supplied scores. It does not validate attribution, sample size, freshness, or whether the score is a good measure of value.
For small inputs or a one-time report, sorting the full collection is often clearer. In Python, for example, heapq.nlargest and nsmallest provide top-K helpers, while the documentation recommends them when K is small relative to the input (heapq). Measure the actual workload before replacing a straightforward sort.
Merge Sort, Quick Sort, and Built-In Sorting
Sorting algorithms order records by a comparison rule. Merge sort has predictable running time that grows roughly in proportion to the number of records multiplied by how many times that number can be halved. It is stable in common implementations, meaning records with equal values keep their previous order. This helps with sorting by several fields: sort by the less important field first, then by the main field using a stable sort.
Quick sort is often efficient, but in its worst case the amount of work can grow roughly as the square of the number of records. That risk depends on how the algorithm chooses a dividing value (the pivot) and how it is implemented. Already-sorted input is not automatically the worst case for every version. Random pivot choices and methods that combine sorting approaches can reduce the risk in different ways.
Most agent builders should start with their language’s built-in sort. Its stability, memory use, and performance are documented or tested by the runtime, and it is easier to maintain than a custom implementation. Python’s built-in sort is stable and adaptive to existing order (Python sorting guide). Choose a specialized algorithm when measured constraints justify it, not because a system processes “a lot” of data in the abstract.
Counting Sort and Radix Sort: Use Key Structure Deliberately
Most sorting methods compare items to decide which comes first. Counting sort can be useful when the values are whole numbers within a known, small range: count each value, then produce the ordered result. Radix sort orders values by looking at one digit or group of digits at a time, using a sort at each step that preserves the order of ties.
A small set of priority levels or status codes may suit counting sort. Identifiers that all have the same number of digits may suit radix sort in a specialized pipeline. These methods can do work that grows in step with the number of records and the size or length of the values, but they use memory and time to prepare those values. A standard sort can still be faster and simpler for ordinary workloads. Keep the original records and test ties, missing values, and consistent formatting of values before adopting a custom method.
Route and Group Work
Topological Sort: Order Dependencies
A topological sort puts tasks in an order that respects their one-way dependencies and contains no circular dependencies. In computer science, that arrangement is called a directed acyclic graph. A reporting pipeline might fetch source data, check it, transform it, calculate metrics, and then write a report. Independent platform fetches can run at the same time; transformation waits until the required fetches finish.
There must be no circular dependency. If task A waits for B, while B also waits for A, no valid order exists. Detect that loop and report the conflicting dependencies instead of letting the workflow wait indefinitely. A scheduler still has to handle retries, time limits, incomplete results, cancellation, and changes a task makes in another system. Sorting gives a valid order; it does not run the tasks or make their effects safe. Princeton’s algorithms reference explains topological order and the graph structure it requires.
Dijkstra: Find a Lowest-Cost Path Under Fixed Conditions
Dijkstra’s algorithm finds the lowest-cost route through a network when every connection has a cost of zero or more. An agent system could use it to compare known routes through data services, with an estimated delay or monetary charge for each connection. Princeton’s shortest-path reference explains why connection costs cannot be negative.
The example becomes misleading if “cost” mixes delay, API charges, token use, quality, permissions, and remaining budget without a clear rule for comparing them. Dijkstra minimizes one total cost, found by adding the costs along each route. It does not decide how much quality is worth, enforce permission, or account for changing prices by itself. If quality is required, rule out routes that fail before comparing costs. If goals conflict, explain how they are compared or show the trade-offs instead of hiding them in an arbitrary score.
The graph also has to represent enough state. If the next route depends on remaining budget, rate limits, freshness, or what data a previous step returned, those facts may need to be part of the node state. For small, fixed choices, a few explicit conditions may be easier to inspect than a shortest-path engine.
Union-Find: Maintain Known Connected Groups
Union-Find, also called disjoint-set union (DSU), is a method for combining groups and checking whether two items belong to the same connected group. It speeds up repeated checks by shortening the links used to find a group and attaching smaller groups beneath larger ones.
It can group records when a defined rule says they are connected, such as belonging to the same campaign template or referencing the same chosen URL. The method cannot tell whether the rule is meaningful or prove that records share a cause. If record A matches B and B matches C, the rule puts all three in one group, even if A and C do not match directly. This carries a connection through a chain of matches. That may be right for finding connected groups, but noisy matches can merge too much.
Use the structure to maintain a grouping that has already been defined. Treat a resulting cluster as a lead for investigation, not a diagnosis that several campaigns share one root cause.
Retain and Retrieve Information
Circular Buffer: Keep a Bounded Recent Window
A circular buffer reuses a fixed amount of computer memory. When full, adding a new item replaces or removes the oldest one, depending on the implementation. It suits recent system measurements, a live display, or a limited troubleshooting window. Python’s bounded deque is one example: when full, adding an item discards one from the other end.
The discarded entries are gone from that buffer. It is therefore unsuitable as the only record of tool calls, approvals, spend, compliance decisions, or actions that may need later audit. Persist those events to an appropriate store, then derive a bounded recent window for fast display or analysis. A circular buffer limits memory; it does not provide durable history, retention policy, or safe deletion.
Compression, Summaries, and Indexes
Compression reduces the space needed to store data. Lossless compression preserves all the original information, so it can be restored exactly. A summary of a long tool result is different: it loses information because details may be left out or changed. Huffman coding, for example, gives shorter codes to more common pieces of data. It does not explain which facts from a conversation a model should keep.
For agent context, first decide what information is needed for the next task. Keep source identifiers, decisions, open questions, and relevant evidence; retrieve raw records when detail matters. Store summaries with links to their source and make clear when they omit information. Do not treat a compressed or generated summary as a complete audit record.
Indexes help find particular information without checking every stored item. A database index can help filter and order records. A trie is a branching structure that can find words with a given beginning. An inverted index lists which records contain each word. Indexes take extra space and upkeep, and may become outdated. Choose the lookup method to fit the question: exact keyword search finds matching words, while semantic search looks for similar meaning. One should not be treated as a substitute for the other.
Where These Patterns Appear in an Agent Stack
| Layer | Common operation | Practical boundary |
|---|---|---|
| Supporting scripts and runtime for skill-guided work | Traverse inputs, order steps, deduplicate runs | The skill guides the procedure; executable code tracks identifiers and retries |
| MCP servers and data tools | Filter, index, rank, paginate | Respect source permissions, pagination, and freshness |
| Storage and retrieval services distributed with plugins | Retrieve records and maintain recent state | The plugin packages access; the service maintains state and durable history |
| CLIs and batch jobs | Sort, scan, and process dependencies | Prefer standard libraries and report partial failures |
| Agent orchestration | Schedule a task graph and route between tools | Keep constraints and action authority outside the ranking algorithm |
These components do not all need hand-built algorithms. A database, runtime library, queue, or workflow engine may already provide the operation with better-tested behavior. Name the invariant in the interface so callers know what a result means.
Three Marketing Workflows
Weekly Performance Reporting
Implement the shared weekly-review brief using the tool guide’s retrieval status and evidence contract. Fetch approved sources in parallel, then use explicit dependencies so source checks precede aggregation and calculated results are checked before report generation. A heap can retain a top-five view as records stream in, provided each campaign has one well-defined aggregate score and minimum-volume rule. Keep a durable history of report runs; use a circular buffer only for a recent activity panel. The reporting model can explain the result after the data and metrics have been checked.
Content and Compliance Review
A scanner can use exact matching for a defined list of prohibited terms and an exact store for processed document IDs. A Bloom filter may reduce lookups at scale, but possible matches go to the authoritative store. A pattern match can flag text for review; it cannot decide legal meaning or reliably detect a prompt injection. Treat external page text as untrusted input, constrain the tools that can act on it, and record why a human or policy review cleared a finding.
Multi-Agent Campaign Workflow
Represent dependencies explicitly: targeting decisions may precede bid configuration, while creative review and platform checks can proceed in parallel. Use a topological scheduler to respect the declared order. If the system has a small set of routes with known, nonnegative costs and stable constraints, shortest-path logic may help compare them. Keep permission, budget caps, approval, and failure recovery as separate checks. Group similar failures only under a defined relationship, and investigate before calling them one cause.
A Practical Rule of Thumb
Choose a pattern by matching the operation to its preconditions:
- Use binary search only on ordered data or when a condition changes once from false to true (or true to false).
- Use BFS or DFS to traverse a graph, not to encode business priority.
- Use string matching for known patterns, not as a semantic or security verdict.
- Use a Bloom filter as a hint, with an exact source for consequential deduplication.
- Use a heap when you need a small ranked subset; use a built-in sort for ordinary batch ordering.
- Use topological sorting when task dependencies contain no loops, Dijkstra when route costs are fixed and can be added together, and Union-Find for a clearly defined rule about which items are connected.
- Use a circular buffer for recent state and a durable store for records that must survive or be audited.
- Treat generated summaries as lossy, and preserve their source evidence when it matters.
Then measure the actual workflow against a simple baseline. Include data retrieval, retries, storage, review, and failure recovery in the comparison. The useful system is the one that meets the workload’s correctness and cost requirements with behavior operators can inspect, not the one with the most impressive algorithm names.
What This Adds to the Series
Skills describe repeatable procedures; tools connect them to systems; orchestration schedules dependent work. Algorithms and data structures help implement some of those operations. They support the model’s work by making retrieval, ordering, grouping, and memory explicit. Their value comes from a precise contract and a tested implementation, not from being deterministic in isolation.
The AI Skills Guide repository remains available as a code companion. Treat its examples as starting points: check their assumptions, versions, tests, and failure behavior against the system you are building.
Use the relevant pattern where its preconditions hold, and return to the workflow’s acceptance cases after changing the implementation. A faster lookup that drops a required campaign, or a scheduler that loses a partial result, has broken the reporting contract even if its local algorithm behaves as designed.
Publication history
Originally published by Performics Labs.