The @tokenring-ai/feedback package provides interactive tools for gathering
human input and reviewing agent proposals. It enables human-in-the-loop
interactions in AI-driven workflows by allowing AI agents to pause execution,
present information to users, and collect feedback through three mechanisms:
- Interactive chat-based questioning
- Browser-based file content review
- React component previews
- Interactive Questioning: Ask humans multiple questions via chat with support for text responses or multiple-choice options
- File Content Review: Display file contents (text, Markdown, HTML, JSON) in browser UIs for approval/reject with comments
- React Component Preview: Bundle and preview React components in browsers for visual feedback and approval
- Seamless Integration: Automatically registers with Token Ring applications
- Auto-Cleanup: Automatic cleanup of temporary files and directories
- Type-Safe: Full TypeScript support with Zod schema validation
bun add @tokenring-ai/feedback- Interactive chat-based questioning with form inputs
- Browser-based file content review with accept/reject functionality
- React component preview with bundling and rendering
- Support for multiple content types (plain text, Markdown, HTML, JSON)
- Automatic temporary file management and cleanup
- Integration with Token Ring agent system
| Tool Name | Display Name | Description |
|---|---|---|
ask_questions |
Feedback/askQuestions |
Ask questions via chat |
feedback_getFileFeedback |
Feedback/getFileFeedback |
Get feedback on file content |
feedback_react-feedback |
Feedback/react-feedback |
Get feedback on React components |
Tool Name: ask_questions
Description: Ask questions to users via chat when feedback is necessary or when uncertain about the proper path to complete a task. If there is uncertainty about the task to be completed, or you are worried about doing something incorrectly, use this tool, as it provides a strong guarantee that you are doing things aligned with the users intents.
Input Schema:
| Parameter | Type | Required | Description |
|---|---|---|---|
| message | string | Yes | Free-form message explaining the problem or uncertainty |
| questions | array | Yes | Array of question objects |
| questions[].question | string | Yes | The specific question to ask the human |
| questions[].choices | string[] | Yes | Suggested choices (empty array for freeform answer) |
Example:
import askQuestions from "@tokenring-ai/feedback/tools/askQuestions";
const result = await askQuestions.execute({
message: "I'm unsure about the approach to take for this refactoring.",
questions: [
{
question: "Which refactoring method do you prefer?",
choices: ["Extract to separate module", "Inline functions", "Keep as-is"]
},
{
question: "Should we add tests before or after?",
choices: [] // Freeform answer
}
]
}, agent);Response Format:
Returns a TokenRingToolResult with message and result properties. The
result contains a formatted string with user responses:
The user has provided the following responses:
Which refactoring method do you prefer?
Extract to separate module
Should we add tests before or after?
After implementation
When no questions are provided, returns { failed: true } with an error message
indicating at least one question is required.
Error Handling:
- Returns
{ failed: true }if no questions are provided - Throws
ToolCallErrorif user does not respond to the question prompt - Throws
ToolCallErrorif invalid response is received (missing Questions property) - Sets default answer ("The user did not provide an answer, use your own judgement") if user provides no answer
- Supports iterative questioning until all questions are answered
- Handles
__other__selection by converting to freeform text input
Tool Name: feedback_getFileFeedback
Description: Present file content to the user for review, solicit feedback
(accept/reject with comments), and optionally write content to a file if
accepted. If the contentType is text/markdown or text/x-markdown, the
content will be rendered as HTML for review.
Input Schema (strict - rejects unknown properties):
| Parameter | Type | Required | Description |
|---|---|---|---|
| filePath | string | Yes | Path where the file content should be saved if accepted |
| content | string | Yes | The actual text content to be reviewed |
| contentType | string | No | MIME type of the content. Defaults to text/plain. Options: text/plain, text/markdown, text/x-markdown, text/html, application/json |
Example:
import getFileFeedback from "@tokenring-ai/feedback/tools/getFileFeedback";
const result = await getFileFeedback.execute({
filePath: "docs/sample.md",
content: "# Sample\n\nThis is **bold** text and `code`.",
contentType: "text/markdown"
}, agent);Response Format:
Returns a TokenRingToolResult where result is a JSON string with the
following structure:
{
"status": "accepted" | "rejected",
"comment": "optional user comment",
"filePath": "path if accepted",
"rejectedFilePath": "original filePath if rejected"
}Supported Content Types:
| Content Type | Rendering Method |
|---|---|
text/plain |
Plain text with HTML escaping in <pre> tag |
text/markdown |
Markdown rendered to HTML using marked.js |
text/x-markdown |
Markdown rendered to HTML using marked.js |
text/html |
Raw HTML content rendered in iframe |
application/json |
JSON with HTML escaping in <pre> tag |
Error Handling:
- Throws
ToolCallErroriffilePathorcontentparameters are missing - Cleanup errors are logged as warnings but do not stop execution
- Requires a running WebHostService (shared host; no per-session server)
- Rejected files are saved with
.rejectedprefix and timestamp
Exported Types:
export interface GetFileFeedbackResult {
status: "accepted" | "rejected";
comment?: string | undefined;
filePath?: string | undefined;
rejectedFilePath?: string | undefined;
}Tool Name: feedback_react-feedback
Description: Show a React component in a browser window for user feedback, allowing accept/reject with optional comments. The component is bundled using esbuild and rendered with React 18 from CDN.
Input Schema (strict - rejects unknown properties):
| Parameter | Type | Required | Description |
|---|---|---|---|
| code | string | Yes | Complete source code of the React component (valid JSX/TSX) |
| file | string | No | Filename/path of the React component to be previewed |
Example:
import reactFeedback from "@tokenring-ai/feedback/tools/react-feedback";
const result = await reactFeedback.execute({
code: `
export default function MyComponent() {
return (
<div style={{ padding: '20px' }}>
<h1>Hello, Feedback!</h1>
<p>This is a React component preview.</p>
</div>
);
}
`,
file: "src/components/MyComponent.tsx"
}, agent);Response Format:
Returns a TokenRingToolResult where result is a JSON string with the
following structure:
// Accepted
{ "status": "accept", "comment": "optional comment" }
// Rejected
{ "status": "reject", "comment": "optional comment" }Technical Details:
- Components are bundled using esbuild with JSX automatic transformation
- React and React DOM are loaded from unpkg CDN (version 18)
- External dependencies (react, react-dom) are treated as global variables
- Components must export a default function component
- Temporary files are automatically cleaned up after feedback is received
- If no
fileis provided, a default filename is generated using ISO timestamp
Error Handling:
- Throws
ToolCallErrorifcodeparameter is missing - Cleanup is performed after file operations
- Feedback session is removed from WebHost after cleanup
- Rejected files are saved with
.rejectedprefix and timestamp
Exported Types:
export interface ReactFeedbackResultAccepted {
status: "accept";
comment?: string | undefined;
}
export interface ReactFeedbackResultRejected {
status: "reject" | "rejected";
comment?: string | undefined;
}
export type ReactFeedbackResult = ReactFeedbackResultAccepted | ReactFeedbackResultRejected;
export interface ToolError {
error: string;
}The package uses a minimal configuration schema that accepts no custom configuration options.
import TokenRingApp from "@tokenring-ai/app";
import feedbackPlugin from "@tokenring-ai/feedback/plugin";
const app = new TokenRingApp();
app.install(feedbackPlugin);
// Tools are now available via the chat serviceThe plugin automatically registers all tools with the ChatService upon installation.
This package does not require any environment variables.
- ChatService: Required for tool registration (handled by plugin)
- WebHostService: Required to serve browser feedback UIs (no per-tool HTTP servers)
- FeedbackService: Registered by this plugin; manages in-flight browser sessions
- FileSystemService: Required by
getFileFeedbackandreactFeedback - Agent: Required for logging and service access
@tokenring-ai/app- Base application framework@tokenring-ai/chat- Chat service@tokenring-ai/agent- Agent system and question schema@tokenring-ai/filesystem- File system service@tokenring-ai/utility- Utility functions@tokenring-ai/web-host- Shared HTTP host for browser feedback UIszod- Schema validationesbuild- React component bundlingesbuild-plugin-external-global- ESBuild plugin for external globalsmarked- Markdown renderingdate-fns- Date formattingopen- Browser launcher
typescript- TypeScript compiler
# Build the package TypeScript files (no Emit)
bun run build# Run tests
bun run test
# Run tests in watch mode
bun run test:watch
# Run tests with coverage
bun run test:coverageMIT License - see LICENSE file for details.