architecture
Telemetry Ethics For Open Source Assistants Failure Patterns: practical systems guide
Technical field guide on telemetry ethics for open source assistants failure patterns and fixes for teams building dependable AI coding workflows.
When your AI coding assistant fails, what do you log—and who gets to see it? Most open-source editor plugins sidestep this question by shipping minimal telemetry or none at all, leaving maintainers blind to real-world failure modes. Commercial tools log aggressively but bury the details behind privacy policies users never read. Neither extreme serves the community well, and both create hidden costs: wasted debugging cycles, silently degraded experiences, and erosion of trust when users discover telemetry they didn't consent to.
A practical telemetry system for open-source AI assistants must balance three forces: actionable failure data for maintainers, clear user control, and minimal server-side storage burden. This guide walks through concrete decisions—what to capture, how to anonymize, when to ask permission—that let you ship assistants that fail gracefully and improve over time without compromising user agency.
What failure data actually matters
Start by distinguishing signal from noise. An assistant that silently times out teaches you nothing; a structured failure event with context (model invoked, edit rejected by linter, retry count) gives you a debugging starting point. Focus on the edges of your agent loop where automation breaks down: validation gate failures, parse errors in generated diffs, constraint violations, network timeouts.
For Goatfied's agent loop (plan → constrain → edit → validate → retry), we track four core failure types: constraint rejections during the planning phase, edits that fail compilation, validation gate timeouts, and retry exhaustion. Each event includes the stage name, anonymized error category (network, syntax, constraint), and retry depth. We explicitly *don't* log user code, raw model outputs, or file paths—those reveal too much about proprietary codebases.
A minimal failure event might look like:
{
"event": "validation_failed",
"stage": "compile",
"error_category": "syntax",
"retry_count": 2,
"model": "gpt-4o",
"timestamp_utc": "2025-01-15T14:23:11Z",
"session_id": "hash_of_machine_id"
}
This structure tells you *where* the loop broke and *how many times* it retried, without exposing what the user was building. Aggregate these events and you'll spot patterns—say, a spike in syntax failures after a model provider updates their API—that individual bug reports would never surface.
Opt-in vs. opt-out: the consent choreography
Open-source projects often default to opt-out telemetry, showing a one-time banner on first launch. This feels polite but trains users to dismiss prompts without reading them. Worse, it front-loads a trust decision before the user has experienced any value from your tool.
A better pattern: ship with telemetry *off* by default, then prompt for opt-in the first time a clear failure occurs—an edit that fails linting, a validation timeout, a retry loop that gives up. The prompt explains what data you'd collect (link to a public schema document) and frames it as "help us fix issues like this one." Users who just hit a pain point are more likely to consent because the value exchange is concrete and immediate.
For self-hosted Goatfied deployments, telemetry stays entirely within the customer's infrastructure unless they explicitly configure an egress endpoint. This shifts the trust boundary: enterprise teams can audit failures internally, then choose to share anonymized aggregates with upstream maintainers. That separation matters for compliance-heavy environments where even failure metadata can't leave the network perimeter.
Anonymization that survives correlation attacks
Hashing machine IDs and stripping file paths isn't enough if your event stream includes timestamps, error sequences, and retry patterns. An attacker with access to your telemetry database and a guess about a specific user's activity can correlate events: "This session hit a TypeScript syntax error at 14:23, retried twice, then succeeded—that matches the timing of PRs in this public repo."
Practical defenses:
- **Jitter timestamps** by ±5 minutes before logging. This breaks fine-grained correlation while preserving hourly/daily failure trends.
- **Rotate session IDs** every 24 hours instead of tying them to machine identity. A persistent session ID across weeks of activity becomes a tracking vector.
- **Bucket rare error categories** into an "other" bin. If only three users hit a specific gRPC timeout variant, logging it verbatim makes them identifiable in your dataset.
- **Sample aggressively** for high-volume events. You don't need every success ping; 1% sampling still surfaces statistically significant failure spikes.
None of these techniques are perfect, but layered together they make correlation attacks expensive enough to deter casual snooping. Document your anonymization pipeline in your repo's `TELEMETRY.md` so security-minded users can audit it.
Handling PII leakage in error messages
Third-party libraries and model APIs often embed user data in exception strings. A Python traceback might include a file path with a username; an LLM error response might echo part of the prompt verbatim. Scrubbing these at the telemetry boundary is critical.
Use a two-pass filter before logging any error message:
1. **Regex-based redaction** for common patterns—file paths, email addresses, API keys (even partial ones). Replace matches with `[REDACTED_PATH]`, `[REDACTED_EMAIL]`, etc.
2. **Length limits**: truncate error strings to 200 characters and append `...` if longer. This preserves the error *type* while clipping away user-specific context that often appears at the end of stack traces.
For model-generated content, never log the raw output. Instead, log a hash of the output (useful for deduplication) and a boolean: "did this output pass validation?" If you need more debugging context, let users manually attach sanitized excerpts via a bug-report helper that shows them exactly what will be shared.
Making telemetry inspectable
The most trust-building feature is a local dashboard that shows users what your assistant has logged, with one-click export and purge. This doesn't have to be fancy—a JSON file in `~/.config/your-tool/telemetry.log` and a CLI command `your-tool telemetry show` will do. Power users will audit it; everyone else benefits from knowing the option exists.
Publish aggregated, anonymized failure stats on a public dashboard (weekly refresh is fine). Show top error categories, retry rates by model, and median time-to-success for common tasks. This transparency turns telemetry from a black box into a community resource: users can see whether their environment is an outlier, and contributors can prioritize fixes based on real impact.
Related reading
- [Goatfied vs Cursor vs GitHub Copilot: a benchmark across 50 real PR tasks](/blog/goatfied-vs-cursor-vs-github-copilot-benchmark-50-pr-tasks)
- [The Goatfied agent loop: how we ship code that actually compiles first try](/blog/goatfied-agent-loop-compiles-first-try)
