From 675860fa3c480da59b91d83a1076db63fe2ce784 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 13 Dec 2025 04:15:13 +0000 Subject: [PATCH] feat: Default rawResponse to true for agents with outputFormat - Update agent controller to automatically return structured JSON directly when an agent has outputFormat defined - Users can still override by explicitly setting rawResponse: false - Prefer structuredOutput over result when returning raw responses - Add comprehensive documentation to README files and CLAUDE.md - Document raw response mode behavior and examples This makes structured output agents more ergonomic by returning the validated JSON directly without requiring rawResponse: true in each request. --- CLAUDE.md | 2 + README.md | 44 +++++++++++++++++++ .../claude-code-plugin-rest-api/README.md | 44 +++++++++++++++++++ .../src/controllers/agent.controller.ts | 34 +++++++++++--- 4 files changed, 117 insertions(+), 7 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 5c3dc47..2d1b5ca 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -109,6 +109,8 @@ Plugins live in `.claude/plugins//` with: | POST | `/v1/agents/:name` | Execute agent (request/response) | | POST | `/v1/agents/:name/stream` | Create SSE stream session | +**Raw Response Mode**: For agents with `outputFormat` defined, the API defaults to returning the structured JSON directly (`rawResponse: true`). This can be overridden by explicitly setting `rawResponse: false` in the request body. For agents without `outputFormat`, the default is to return wrapped responses with metadata. + ### Plugin Discovery (Secondary) | Method | Endpoint | Description | diff --git a/README.md b/README.md index 453aa00..f9499e9 100644 --- a/README.md +++ b/README.md @@ -244,6 +244,50 @@ The response includes `structuredOutput` with validated JSON: } ``` +#### Raw Response Mode + +For agents with `outputFormat`, the API automatically returns the structured JSON directly (raw response mode). You can override this behavior: + +```bash +# Default behavior - returns structured JSON directly +curl -X POST http://localhost:3000/v1/agents/code-analyzer \ + -H "Content-Type: application/json" \ + -d '{"prompt": "Analyze the number 42"}' + +# Returns: +{ + "summary": "Well-structured code with minor issues", + "score": 8, + "issues": [...] +} + +# Get wrapped response with metadata instead +curl -X POST http://localhost:3000/v1/agents/code-analyzer \ + -H "Content-Type: application/json" \ + -d '{"prompt": "Analyze the number 42", "rawResponse": false}' + +# Returns: +{ + "success": true, + "result": "...", + "structuredOutput": { "summary": "...", "score": 8, ... }, + "cost": 0.02, + "turns": 1, + "usage": { "inputTokens": 123, "outputTokens": 45 } +} +``` + +For agents without `outputFormat`, you can still enable raw response mode: + +```bash +curl -X POST http://localhost:3000/v1/agents/math-helper \ + -H "Content-Type: application/json" \ + -d '{"prompt": "What is 2+2?", "rawResponse": true}' + +# Returns just the text response: +The answer is 4. +``` + ### Custom MCP Tools Example Create in-process MCP servers with custom tools using `createSdkMcpServer` and `tool`: diff --git a/packages/claude-code-plugin-rest-api/README.md b/packages/claude-code-plugin-rest-api/README.md index 453aa00..f9499e9 100644 --- a/packages/claude-code-plugin-rest-api/README.md +++ b/packages/claude-code-plugin-rest-api/README.md @@ -244,6 +244,50 @@ The response includes `structuredOutput` with validated JSON: } ``` +#### Raw Response Mode + +For agents with `outputFormat`, the API automatically returns the structured JSON directly (raw response mode). You can override this behavior: + +```bash +# Default behavior - returns structured JSON directly +curl -X POST http://localhost:3000/v1/agents/code-analyzer \ + -H "Content-Type: application/json" \ + -d '{"prompt": "Analyze the number 42"}' + +# Returns: +{ + "summary": "Well-structured code with minor issues", + "score": 8, + "issues": [...] +} + +# Get wrapped response with metadata instead +curl -X POST http://localhost:3000/v1/agents/code-analyzer \ + -H "Content-Type: application/json" \ + -d '{"prompt": "Analyze the number 42", "rawResponse": false}' + +# Returns: +{ + "success": true, + "result": "...", + "structuredOutput": { "summary": "...", "score": 8, ... }, + "cost": 0.02, + "turns": 1, + "usage": { "inputTokens": 123, "outputTokens": 45 } +} +``` + +For agents without `outputFormat`, you can still enable raw response mode: + +```bash +curl -X POST http://localhost:3000/v1/agents/math-helper \ + -H "Content-Type: application/json" \ + -d '{"prompt": "What is 2+2?", "rawResponse": true}' + +# Returns just the text response: +The answer is 4. +``` + ### Custom MCP Tools Example Create in-process MCP servers with custom tools using `createSdkMcpServer` and `tool`: diff --git a/packages/claude-code-plugin-rest-api/src/controllers/agent.controller.ts b/packages/claude-code-plugin-rest-api/src/controllers/agent.controller.ts index adb186f..2ba96b1 100644 --- a/packages/claude-code-plugin-rest-api/src/controllers/agent.controller.ts +++ b/packages/claude-code-plugin-rest-api/src/controllers/agent.controller.ts @@ -20,6 +20,8 @@ class ExecuteAgentDto { prompt!: string; /** * When true, returns the agent's output directly without wrapper. + * For agents with outputFormat, defaults to true (returns structured JSON directly). + * For other agents, defaults to false (returns wrapped response with metadata). * Content-Type is auto-detected: JSON if parseable, otherwise text/plain. */ rawResponse?: boolean; @@ -77,6 +79,7 @@ export class AgentController { * Execute an agent (request/response mode) * * By default, returns a wrapped response with metadata (success, result, cost, turns, usage). + * For agents with outputFormat, rawResponse defaults to true (returns structured JSON directly). * When `rawResponse: true`, returns the agent's output directly with auto-detected Content-Type. */ @Post(':name') @@ -92,6 +95,12 @@ export class AgentController { ) { this.logger.log(`Executing agent: ${name}`); + // Get agent config to check for outputFormat + const config = this.agentService.getAgentConfig(name); + if (!config) { + throw new NotFoundException(`Agent '${name}' not found`); + } + const result = await this.agentService.execute(name, dto.prompt); if (!result.success && result.error?.includes('not found')) { @@ -105,15 +114,26 @@ export class AgentController { ); } + // Default rawResponse to true for agents with outputFormat + const shouldReturnRaw = dto.rawResponse ?? (config.outputFormat !== undefined); + // Handle raw response mode with auto-detect Content-Type - if (dto.rawResponse && result.result) { - try { - const parsed = JSON.parse(result.result); + if (shouldReturnRaw) { + // For structured output, prefer structuredOutput over result + if (result.structuredOutput !== undefined) { res.setHeader('Content-Type', 'application/json'); - return parsed; - } catch { - res.setHeader('Content-Type', 'text/plain'); - return result.result; + return result.structuredOutput; + } + + if (result.result) { + try { + const parsed = JSON.parse(result.result); + res.setHeader('Content-Type', 'application/json'); + return parsed; + } catch { + res.setHeader('Content-Type', 'text/plain'); + return result.result; + } } }