Use Firegoat
Agent feedback
Embed @firegoat/feedback in your CLI or MCP so agents can report to you.
Let coding agents that use your product send feedback to you through Firegoat. Embed @firegoat/feedback in your CLI or MCP server; reports land on your org's Firegoat feedback page, deduped against what agents already reported. No Firegoat API key is required for this package.
This is not the same as Firegoat's own MCP send_feedback tool, which files feedback to the Firegoat team about evals, the API, or the dashboard. This package is for your product domain so agents can tell you about bugs and gaps in your tool.
Install
npm i @firegoat/feedbackDuring local development, npm link in your package repo and npm link @firegoat/feedback in the consumer.
Core API
import { FeedbackClient, FeedbackError } from "@firegoat/feedback";
const feedback = new FeedbackClient({ domain: "mytool.dev" });
try {
const { id, similarCount } = await feedback.send({
title: "flag --region is not in the docs", // 8–200 chars
body: "tried `mytool deploy --region us`, got unknown flag",
type: "bug", // "bug" | "feature_request" | "feedback"
meta: { agent: "claude-code", model: "claude-opus-5-5" },
});
} catch (err) {
if (err instanceof FeedbackError && err.code === "rate_limited") {
console.error(`retry in ${err.retryAfterSeconds}s`);
}
throw err;
}send() accepts title (8–200 characters), optional body, type (bug, feature_request, or feedback), and optional meta (arbitrary JSON for agent, model, version, and similar context). Failures throw FeedbackError with status, code, message, and sometimes retryAfterSeconds (for rate limits) or detected (for secret detection).
Device token and rate limits
On the first send(), the client registers a device and saves its token to ~/.config/firegoat/feedback-device.json (mode 0600; $XDG_CONFIG_HOME is respected). That raises the limit from 5 to 30 reports per day per IP. A rejected token is re-registered once. Outside Node, the token stays in memory.
Change storage with device: fileDeviceStore(path), device: memoryDeviceStore(), or device: false, or pass token to supply your own.
Secrets
A report that looks like it contains a secret fails with code: "possible_secret". Redact and retry, or pass maskSecrets: true so the server stores a masked copy.
Endpoint
baseUrl defaults to https://firegoat.ai/evals. Override with the baseUrl option or the FEEDBACK_API_URL environment variable.
Telemetry is not part of this package yet.
Drop-in: CLI command
runFeedbackCommand adds a feedback subcommand with help written for agents, --body - from stdin, and exit codes 0 sent, 2 service failed, 3 usage:
import { FeedbackClient, runFeedbackCommand } from "@firegoat/feedback";
const client = new FeedbackClient({ domain: "mytool.dev" });
if (argv[0] === "feedback") {
process.exitCode = await runFeedbackCommand(argv.slice(1), {
client,
name: "mytool",
version,
});
}Drop-in: MCP tool
feedbackTool registers a send_feedback tool on your MCP server (name and description tuned so agents actually call it). You wire the zod schema:
import { FeedbackClient, feedbackTool } from "@firegoat/feedback";
import { z } from "zod";
const tool = feedbackTool(new FeedbackClient({ domain: "mytool.dev" }), {
product: "mytool",
});
server.registerTool(
tool.name,
{
description: tool.description,
inputSchema: {
title: z.string(),
body: z.string().optional(),
type: z.enum(tool.types).optional(),
},
},
tool.handler,
);Both helpers attach agent name (claude-code, codex, cursor — from the environment), OS, and Node version in meta.
agentspa
agentspa is a standalone CLI an agent runs itself against any domain. @firegoat/feedback is what you embed so reports go to your Firegoat feedback page for your domain. Same underlying API; different integration path.