Skip to content

Add response policy and cost control to prevent unbounded LLM feedback loop #25

Description

@devfire

🔁 UNBOUNDED CONVERSATION FEEDBACK LOOP

Location: src/processor.rs:54-104

Problem

loop {
    match message_receiver.receive_message().await {
        Ok(message) => {
            // ... call LLM ...
            network_manager.send_message(&response_message).await?;
        }
        Err(e) => { ... }
    }
}

The LLM processing task responds to every incoming message unconditionally. There is no "should I respond?" gate, no cooldown, no per-agent budget, and no turn-taking (confirmed: no rate/limit/cooldown/probability logic exists anywhere in the codebase).

Issues

  • Infinite ping-pong: with two agents, each message triggers a response that triggers a response, ad infinitum. With N agents the per-round message volume is O(N²), unbounded in time.
  • Unbounded API cost: every response is a paid LLM call, so the swarm incurs open-ended, uncapped spending the moment it starts.
  • Startup thundering herd: every agent broadcasts a bootstrap greeting (processor.rs:46-52), so N starting agents immediately hand each peer N−1 prompts at once.
  • The timestamp field is collected but never used for ordering/dedup, so UDP reordering/duplication is silently absorbed.

Suggested Fix

Introduce a response policy before calling the LLM, e.g.:

// Only respond when directly addressed, plus a rate limit / budget
if !should_respond(&message, &agent_id) { continue; }

Combine with: a per-agent rate limit (e.g. tokio::time::Interval / token bucket), a configurable global message budget, and an optional addressing model (@agent-id).

Priority: High — the biggest architectural gap; this is a correctness/cost problem, distinct from the plumbing-focused open issues (#10/#13/#14).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions