Predicting Agent Behavior with Automata
Listen to the summary
Uses a voice available on your device
Audio options
On this page 5 sections
Related concepts 1 concepts
Key Takeaways
- FSM state context improves next-step prediction cross-entropy by 0.155 bits, representing a 21 percent improvement.
- The system achieves a held-out AUROC of up to 0.94 in identifying potential agent failures.
- An online monitor can rank failing runs higher than passing runs from partial traces to trigger early stops.
- The approach was validated against twelve public datasets and nine existing baselines.
Summary & Methodology Analysis
The researchers represent agent execution traces as a deterministic finite state machine (FSM), a computational model that uses defined states and transitions to represent system logic. By inserting activity sequences into a prefix tree and merging states based on the last-activity right congruence, the method constructs a structural map of agent behavior. The authors refine this model by filtering out rare transitions that only occur once, ensuring the automaton reflects common patterns. This structural backbone provides a state-based context that acts as a signal for predictive models.
To apply this to real-time operations, the team extracts per-state behavioral features, including metrics such as visit frequency and error rates. These features allow an online monitor to analyze partial traces and distinguish between successful and failing execution paths. When integrated into next-step prediction tasks, the FSM state context improves cross-entropy by 0.155 bits (21 percent) compared to methods without this context. This is particularly effective for failure prediction, where the features achieve a held-out AUROC of up to 0.94, enabling the system to trigger early stopping before a failing task completes.
While the model provides robust monitoring, it faces a fundamental limitation regarding security. The FSM accepts the directly-follows closure of observed traces rather than the agent’s true generating language. This means the system remains vulnerable to adversarial traces that are carefully constructed to preserve activity bigram statistics, potentially allowing malicious sequences to be accepted as valid. The authors validate these results using the SWE-agent and ATBench datasets, testing against a wide range of baselines including RPNI, EDSM, Alergia, and k-Tails.
Interactive System Flowchart
Illustrative Implementation
A short sketch of the paper's core idea, not the authors' own code.
# Illustrative sketch (not from the paper)
import collections
import torch
import torch.nn as nn
# 1. Insert activity sequences into a prefix tree (trie)
def build_trie(traces):
root = {}
for seq in traces:
node = root
for act in seq:
node = node.setdefault(act, {})
return root
# 2. Merge states that share the same last activity (right congruence)
def merge_states(trie):
# map last activity -> list of nodes
groups = collections.defaultdict(list)
def dfs(node, path):
if not node:
return
last = path[-1] if path else None
groups[last].append(node)
for act, child in node.items():
dfs(child, path + [act])
dfs(trie, [])
# naive merge: collapse groups into a single representative
fsm = {'states': [], 'trans': collections.Counter()}
for last, nodes in groups.items():
state_id = len(fsm['states'])
fsm['states'].append(last)
for n in nodes:
for act in n:
fsm['trans'][(state_id, act)] += 1
return fsm
# 3. Filter rare transitions that appear exactly once
def filter_rare(trans_counter):
return {k: v for k, v in trans_counter.items() if v > 1}
# 4. Use FSM state as context for next‑step prediction (PyTorch example)
class NextStepModel(nn.Module):
def __init__(self, n_states, vocab_size, embed_dim=32):
super().__init__()
self.state_emb = nn.Embedding(n_states, embed_dim)
self.token_emb = nn.Embedding(vocab_size, embed_dim)
self.fc = nn.Linear(embed_dim * 2, vocab_size)
def forward(self, state_idx, prev_token):
s = self.state_emb(state_idx)
t = self.token_emb(prev_token)
x = torch.cat([s, t], dim=-1)
return self.fc(x)
# 5. Extract per‑state behavioral features (frequency, avg length, error flag)
def extract_features(traces, fsm):
freq = collections.Counter()
length_sum = collections.Counter()
error = collections.Counter()
for seq in traces:
state = 0 # start state placeholder
for act in seq:
freq[state] += 1
length_sum[state] += len(act)
if act.lower().startswith('error'):
error[state] = 1
# transition to next state (simplified)
state = (state + 1) % len(fsm['states'])
features = {}
for s in range(len(fsm['states'])):
features[s] = {
'visit_freq': freq[s],
'avg_len': length_sum[s] / max(1, freq[s]),
'has_error': error.get(s, 0)
}
return features
// Illustrative sketch (not from the paper)
const fs = require('fs');
// 1. Build a trie from activity traces (array of arrays)
function buildTrie(traces) {
const root = {};
for (const seq of traces) {
let node = root;
for (const act of seq) {
if (!node[act]) node[act] = {};
node = node[act];
}
}
return root;
}
// 2. Merge states that share the same last activity (right congruence)
function mergeStates(trie) {
const groups = {};
function dfs(node, path) {
const last = path.length ? path[path.length - 1] : null;
if (!groups[last]) groups[last] = [];
groups[last].push(node);
for (const act in node) {
dfs(node[act], path.concat(act));
}
}
dfs(trie, []);
const fsm = { states: [], trans: {} };
let stateId = 0;
for (const last in groups) {
fsm.states.push(last);
for (const n of groups[last]) {
for (const act in n) {
const key = `${stateId}|${act}`;
fsm.trans[key] = (fsm.trans[key] || 0) + 1;
}
}
stateId++;
}
return fsm;
}
// 3. Filter transitions that appear exactly once
function filterRare(trans) {
const filtered = {};
for (const k in trans) {
if (trans[k] > 1) filtered[k] = trans[k];
}
return filtered;
}
// 4. Use FSM state as context for a next‑step predictor (placeholder function)
function predictNext(stateIdx, prevToken, model) {
// model could be a TensorFlow.js model; here we just illustrate the API
return model.predict({ state: stateIdx, token: prevToken });
}
// 5. Extract per‑state behavioral features
function extractFeatures(traces, fsm) {
const freq = {};
const lenSum = {};
const error = {};
for (const seq of traces) {
let state = 0; // start state placeholder
for (const act of seq) {
freq[state] = (freq[state] || 0) + 1;
lenSum[state] = (lenSum[state] || 0) + act.length;
if (/^error/i.test(act)) error[state] = 1;
state = (state + 1) % fsm.states.length; // simplified transition
}
}
const features = {};
for (let s = 0; s < fsm.states.length; s++) {
const visits = freq[s] || 0;
features[s] = {
visitFreq: visits,
avgLen: visits ? lenSum[s] / visits : 0,
hasError: error[s] || 0
};
}
return features;
}
Cross-Examination & FAQs
A deeper dive clarifying mechanics, constraints, and baseline evaluations.
Q1. What is the main goal of this research?
The goal is to improve how we predict the next steps of agents and detect failures in their execution traces by using finite state machine models.
Q2. How does this method help with software reliability?
It uses an online monitor to analyze partial traces and identify failing runs early, allowing for automatic early stopping before a task finishes.
Q3. Is this approach tested on real-world data?
Yes, the method was evaluated on twelve public datasets, including the SWE-agent and ATBench.
Q4. What is the improvement in prediction accuracy?
Using FSM state context improves cross-entropy by 0.155 bits, or 21 percent, compared to methods that do not use state context.
Q5. What is the AUROC for failure prediction?
The per-state behavioral features reach a held-out AUROC of up to 0.94.
Q6. What are the specific limitations regarding adversarial attacks?
Because the model uses a directly-follows automaton closure, adversarial traces that preserve activity bigram statistics can still be accepted by the FSM.
Q7. Which baselines were used for comparison?
The researchers compared their work against nine baselines, including RPNI, EDSM, Alergia, k-Tails, HMMs, process mining, and workflow extraction methods.
Q8. Does the paper specify the computational cost of running this monitor?
The paper does not specify the computational cost.
Q9. Does the method identify the agent's true generating language?
No, it explicitly extracts the directly-follows closure of the observed traces rather than the true generating language.