Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ Plugins live in `.claude/plugins/<plugin-name>/` 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 |
Expand Down
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`:
Expand Down
44 changes: 44 additions & 0 deletions packages/claude-code-plugin-rest-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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')
Expand All @@ -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')) {
Expand All @@ -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;
}
}
}

Expand Down