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
157 changes: 157 additions & 0 deletions comfy-router-limitations.mdx

Large diffs are not rendered by default.

534 changes: 534 additions & 0 deletions comfy-router-quickstart.mdx

Large diffs are not rendered by default.

339 changes: 339 additions & 0 deletions comfy-router-reference.mdx

Large diffs are not rendered by default.

167 changes: 154 additions & 13 deletions openapi-v2.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions router-schemas/anthropic/claude-fable-5.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"openapi":"3.0.2","info":{"title":"anthropic/claude-fable-5","description":"The request body Comfy Router accepts for the model \"anthropic/claude-fable-5\", and the response body it returns. The INPUT schema is the same schema the server validates a call against before it reaches the provider, so what is published and what is enforced cannot differ. The OUTPUT schema describes the provider's native result document exactly as Router returns it: Router does not validate, narrow or re-envelope the response, so the output schema is descriptive rather than enforced, and Comfy owns no output shape of its own.","version":"f7ffd6c12415"},"paths":{"/v2/models/anthropic/claude-fable-5":{"post":{"operationId":"runRouterModel","summary":"Run anthropic/claude-fable-5 synchronously.","security":[{"BearerAuth":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"additionalProperties":true,"description":"This model's input has not been narrowed by Comfy yet. Router forwards the body to the partner unchanged, so the partner's own documentation is authoritative until a schema is authored for this model. Any JSON object is accepted here and by the server's pre-provider validation alike.","type":"object"}}}},"responses":{"200":{"description":"OK - the model's native JSON output, returned unchanged; the schema describes the provider's terminal result document as Router returns it.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AnthropicCreateMessageResponse"},{"properties":{"content":{"description":"The reply's content blocks, in order. Present on every completed message; empty when the turn produced nothing.","items":{"additionalProperties":true,"description":"One Messages API content block. `type` names the block's kind and decides which sibling fields it carries; unknown kinds pass through unchanged.","properties":{"text":{"description":"The block's text. Present on `text` blocks and absent on every other kind.","type":"string"},"type":{"description":"The block kind. `text` is the one that carries `text`; `thinking`, `redacted_thinking`, `tool_use`, `server_tool_use` and the tool-result blocks are the others Anthropic sends today, and the list is open.","type":"string"}},"type":"object"},"type":"array"}},"required":["content"],"type":"object"}],"description":"Comfy Router output schema for the Anthropic Claude models: the non-streaming Messages API document `POST /proxy/anthropic/v1/messages` answers with, forwarded unchanged. The operation is DIRECT RETURN — `routerresult/classification.go` records `{provider: anthropic, endpoint: /v1/messages}` as `ReturnModeDirect` with no poll route, because `messagesProxy`'s `ModifyResponse` reads `usage` off the finished body and meters it synchronously through `TrackUsage` — so the body a caller receives is the completed message on the original call, never a task handle.\nRouter CAPTURES rather than streams. `stream` is a settled field for this operation (`routerSettledBoolFields`, server/middleware): a Router request naming `stream` is forwarded with it set to FALSE, so a Router caller always receives this single JSON document and never the `text/event-stream` of message events the `/proxy/` route serves when `stream: true`. Send `stream` false or omit it; the `text/event-stream` half of the `/proxy/` operation's 200 has no Router counterpart.\nThe reply text is at `content[].text`. `content` is the Messages API block list and it is ALWAYS present on a completed message, but it is not uniformly text: a block carries `type`, and only `text` blocks carry `text`. `thinking`, `tool_use` and the server-tool blocks are legitimate members that carry no `text` at all, so a caller must select on `type` rather than read `content[0].text` — and an empty `content` is what a request that generated nothing looks like. The sibling top-level fields are NOT the result: `stop_reason` and `usage` are populated on a turn that emitted no content, and `model` is an echo of the request.","example":{"content":[{"text":"ok","type":"text"}],"id":"msg_01ExampleInvalidPlaceholder","model":"claude-haiku-4-5-20251001","role":"assistant","stop_reason":"end_turn","stop_sequence":null,"type":"message","usage":{"input_tokens":16,"output_tokens":3}}}}}}}}}},"components":{"schemas":{"AnthropicCacheCreationUsage":{"description":"Per-TTL breakdown of cache-write input tokens for an Anthropic Messages API call.","properties":{"ephemeral_1h_input_tokens":{"type":"integer"},"ephemeral_5m_input_tokens":{"type":"integer"}},"type":"object"},"AnthropicCreateMessageResponse":{"additionalProperties":true,"description":"JSON shape of a non-streaming Messages API response. Most fields pass through; the proxy reads `usage` for billing.","properties":{"id":{"type":"string"},"model":{"type":"string"},"role":{"type":"string"},"stop_reason":{"nullable":true,"type":"string"},"stop_sequence":{"nullable":true,"type":"string"},"type":{"type":"string"},"usage":{"$ref":"#/components/schemas/AnthropicMessagesUsage"}},"type":"object"},"AnthropicMessagesUsage":{"description":"Token usage for an Anthropic Messages API call.","properties":{"cache_creation":{"$ref":"#/components/schemas/AnthropicCacheCreationUsage"},"cache_creation_input_tokens":{"type":"integer"},"cache_read_input_tokens":{"type":"integer"},"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"}},"type":"object"}},"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"},"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"x-comfy-router-model-id":"anthropic/claude-fable-5","x-comfy-input-schema-authored":false,"x-comfy-output-schema-authored":true}
1 change: 1 addition & 0 deletions router-schemas/anthropic/claude-haiku-4-5-20251001.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"openapi":"3.0.2","info":{"title":"anthropic/claude-haiku-4-5-20251001","description":"The request body Comfy Router accepts for the model \"anthropic/claude-haiku-4-5-20251001\", and the response body it returns. The INPUT schema is the same schema the server validates a call against before it reaches the provider, so what is published and what is enforced cannot differ. The OUTPUT schema describes the provider's native result document exactly as Router returns it: Router does not validate, narrow or re-envelope the response, so the output schema is descriptive rather than enforced, and Comfy owns no output shape of its own.","version":"f7ffd6c12415"},"paths":{"/v2/models/anthropic/claude-haiku-4-5-20251001":{"post":{"operationId":"runRouterModel","summary":"Run anthropic/claude-haiku-4-5-20251001 synchronously.","security":[{"BearerAuth":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"additionalProperties":true,"description":"This model's input has not been narrowed by Comfy yet. Router forwards the body to the partner unchanged, so the partner's own documentation is authoritative until a schema is authored for this model. Any JSON object is accepted here and by the server's pre-provider validation alike.","type":"object"}}}},"responses":{"200":{"description":"OK - the model's native JSON output, returned unchanged; the schema describes the provider's terminal result document as Router returns it.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AnthropicCreateMessageResponse"},{"properties":{"content":{"description":"The reply's content blocks, in order. Present on every completed message; empty when the turn produced nothing.","items":{"additionalProperties":true,"description":"One Messages API content block. `type` names the block's kind and decides which sibling fields it carries; unknown kinds pass through unchanged.","properties":{"text":{"description":"The block's text. Present on `text` blocks and absent on every other kind.","type":"string"},"type":{"description":"The block kind. `text` is the one that carries `text`; `thinking`, `redacted_thinking`, `tool_use`, `server_tool_use` and the tool-result blocks are the others Anthropic sends today, and the list is open.","type":"string"}},"type":"object"},"type":"array"}},"required":["content"],"type":"object"}],"description":"Comfy Router output schema for the Anthropic Claude models: the non-streaming Messages API document `POST /proxy/anthropic/v1/messages` answers with, forwarded unchanged. The operation is DIRECT RETURN — `routerresult/classification.go` records `{provider: anthropic, endpoint: /v1/messages}` as `ReturnModeDirect` with no poll route, because `messagesProxy`'s `ModifyResponse` reads `usage` off the finished body and meters it synchronously through `TrackUsage` — so the body a caller receives is the completed message on the original call, never a task handle.\nRouter CAPTURES rather than streams. `stream` is a settled field for this operation (`routerSettledBoolFields`, server/middleware): a Router request naming `stream` is forwarded with it set to FALSE, so a Router caller always receives this single JSON document and never the `text/event-stream` of message events the `/proxy/` route serves when `stream: true`. Send `stream` false or omit it; the `text/event-stream` half of the `/proxy/` operation's 200 has no Router counterpart.\nThe reply text is at `content[].text`. `content` is the Messages API block list and it is ALWAYS present on a completed message, but it is not uniformly text: a block carries `type`, and only `text` blocks carry `text`. `thinking`, `tool_use` and the server-tool blocks are legitimate members that carry no `text` at all, so a caller must select on `type` rather than read `content[0].text` — and an empty `content` is what a request that generated nothing looks like. The sibling top-level fields are NOT the result: `stop_reason` and `usage` are populated on a turn that emitted no content, and `model` is an echo of the request.","example":{"content":[{"text":"ok","type":"text"}],"id":"msg_01ExampleInvalidPlaceholder","model":"claude-haiku-4-5-20251001","role":"assistant","stop_reason":"end_turn","stop_sequence":null,"type":"message","usage":{"input_tokens":16,"output_tokens":3}}}}}}}}}},"components":{"schemas":{"AnthropicCacheCreationUsage":{"description":"Per-TTL breakdown of cache-write input tokens for an Anthropic Messages API call.","properties":{"ephemeral_1h_input_tokens":{"type":"integer"},"ephemeral_5m_input_tokens":{"type":"integer"}},"type":"object"},"AnthropicCreateMessageResponse":{"additionalProperties":true,"description":"JSON shape of a non-streaming Messages API response. Most fields pass through; the proxy reads `usage` for billing.","properties":{"id":{"type":"string"},"model":{"type":"string"},"role":{"type":"string"},"stop_reason":{"nullable":true,"type":"string"},"stop_sequence":{"nullable":true,"type":"string"},"type":{"type":"string"},"usage":{"$ref":"#/components/schemas/AnthropicMessagesUsage"}},"type":"object"},"AnthropicMessagesUsage":{"description":"Token usage for an Anthropic Messages API call.","properties":{"cache_creation":{"$ref":"#/components/schemas/AnthropicCacheCreationUsage"},"cache_creation_input_tokens":{"type":"integer"},"cache_read_input_tokens":{"type":"integer"},"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"}},"type":"object"}},"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"},"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"x-comfy-router-model-id":"anthropic/claude-haiku-4-5-20251001","x-comfy-input-schema-authored":false,"x-comfy-output-schema-authored":true}
1 change: 1 addition & 0 deletions router-schemas/anthropic/claude-opus-4-6.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"openapi":"3.0.2","info":{"title":"anthropic/claude-opus-4-6","description":"The request body Comfy Router accepts for the model \"anthropic/claude-opus-4-6\", and the response body it returns. The INPUT schema is the same schema the server validates a call against before it reaches the provider, so what is published and what is enforced cannot differ. The OUTPUT schema describes the provider's native result document exactly as Router returns it: Router does not validate, narrow or re-envelope the response, so the output schema is descriptive rather than enforced, and Comfy owns no output shape of its own.","version":"f7ffd6c12415"},"paths":{"/v2/models/anthropic/claude-opus-4-6":{"post":{"operationId":"runRouterModel","summary":"Run anthropic/claude-opus-4-6 synchronously.","security":[{"BearerAuth":[]},{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"additionalProperties":true,"description":"This model's input has not been narrowed by Comfy yet. Router forwards the body to the partner unchanged, so the partner's own documentation is authoritative until a schema is authored for this model. Any JSON object is accepted here and by the server's pre-provider validation alike.","type":"object"}}}},"responses":{"200":{"description":"OK - the model's native JSON output, returned unchanged; the schema describes the provider's terminal result document as Router returns it.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AnthropicCreateMessageResponse"},{"properties":{"content":{"description":"The reply's content blocks, in order. Present on every completed message; empty when the turn produced nothing.","items":{"additionalProperties":true,"description":"One Messages API content block. `type` names the block's kind and decides which sibling fields it carries; unknown kinds pass through unchanged.","properties":{"text":{"description":"The block's text. Present on `text` blocks and absent on every other kind.","type":"string"},"type":{"description":"The block kind. `text` is the one that carries `text`; `thinking`, `redacted_thinking`, `tool_use`, `server_tool_use` and the tool-result blocks are the others Anthropic sends today, and the list is open.","type":"string"}},"type":"object"},"type":"array"}},"required":["content"],"type":"object"}],"description":"Comfy Router output schema for the Anthropic Claude models: the non-streaming Messages API document `POST /proxy/anthropic/v1/messages` answers with, forwarded unchanged. The operation is DIRECT RETURN — `routerresult/classification.go` records `{provider: anthropic, endpoint: /v1/messages}` as `ReturnModeDirect` with no poll route, because `messagesProxy`'s `ModifyResponse` reads `usage` off the finished body and meters it synchronously through `TrackUsage` — so the body a caller receives is the completed message on the original call, never a task handle.\nRouter CAPTURES rather than streams. `stream` is a settled field for this operation (`routerSettledBoolFields`, server/middleware): a Router request naming `stream` is forwarded with it set to FALSE, so a Router caller always receives this single JSON document and never the `text/event-stream` of message events the `/proxy/` route serves when `stream: true`. Send `stream` false or omit it; the `text/event-stream` half of the `/proxy/` operation's 200 has no Router counterpart.\nThe reply text is at `content[].text`. `content` is the Messages API block list and it is ALWAYS present on a completed message, but it is not uniformly text: a block carries `type`, and only `text` blocks carry `text`. `thinking`, `tool_use` and the server-tool blocks are legitimate members that carry no `text` at all, so a caller must select on `type` rather than read `content[0].text` — and an empty `content` is what a request that generated nothing looks like. The sibling top-level fields are NOT the result: `stop_reason` and `usage` are populated on a turn that emitted no content, and `model` is an echo of the request.","example":{"content":[{"text":"ok","type":"text"}],"id":"msg_01ExampleInvalidPlaceholder","model":"claude-haiku-4-5-20251001","role":"assistant","stop_reason":"end_turn","stop_sequence":null,"type":"message","usage":{"input_tokens":16,"output_tokens":3}}}}}}}}}},"components":{"schemas":{"AnthropicCacheCreationUsage":{"description":"Per-TTL breakdown of cache-write input tokens for an Anthropic Messages API call.","properties":{"ephemeral_1h_input_tokens":{"type":"integer"},"ephemeral_5m_input_tokens":{"type":"integer"}},"type":"object"},"AnthropicCreateMessageResponse":{"additionalProperties":true,"description":"JSON shape of a non-streaming Messages API response. Most fields pass through; the proxy reads `usage` for billing.","properties":{"id":{"type":"string"},"model":{"type":"string"},"role":{"type":"string"},"stop_reason":{"nullable":true,"type":"string"},"stop_sequence":{"nullable":true,"type":"string"},"type":{"type":"string"},"usage":{"$ref":"#/components/schemas/AnthropicMessagesUsage"}},"type":"object"},"AnthropicMessagesUsage":{"description":"Token usage for an Anthropic Messages API call.","properties":{"cache_creation":{"$ref":"#/components/schemas/AnthropicCacheCreationUsage"},"cache_creation_input_tokens":{"type":"integer"},"cache_read_input_tokens":{"type":"integer"},"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"}},"type":"object"}},"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"},"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"x-comfy-router-model-id":"anthropic/claude-opus-4-6","x-comfy-input-schema-authored":false,"x-comfy-output-schema-authored":true}
Loading
Loading