{"_id":"@carloscortezcloud/styrr-strands","_rev":"2-fbd339c15418d182165821bb7afbddf1","name":"@carloscortezcloud/styrr-strands","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@carloscortezcloud/styrr-strands","version":"0.1.0","keywords":["strands","styrr","llm","fallback","model-provider"],"license":"Apache-2.0","_id":"@carloscortezcloud/styrr-strands@0.1.0","maintainers":[{"name":"carloscortezcloud","email":"carlos@cortez.cloud"}],"homepage":"https://github.com/breakingthecloud/styrr#readme","bugs":{"url":"https://github.com/breakingthecloud/styrr/issues"},"dist":{"shasum":"d81e11715278da487000011ceaddbbda18eedf6c","tarball":"https://registry.npmjs.org/@carloscortezcloud/styrr-strands/-/styrr-strands-0.1.0.tgz","fileCount":6,"integrity":"sha512-oVgZaDmcbIHwgmwYesTwUUN5NURrwVb1V1WMzwfKdS+zAtW6K71WJeHAIfldMzVA7y+xJcKu8l3WKvlxGTFVRw==","signatures":[{"sig":"MEUCIQC3aweCwmZPcHupW74cNnf3v/apFr5xp5JXn1CbLdZPVwIgfV5r7DBkxkS0MspEaVeE1h9ED1o4RbPP5M7+Af3DSzg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12982},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","gitHead":"e07c64244e08b496398fb860de63b37b7ca0743e","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"carloscortezcloud","email":"carlos@cortez.cloud"},"repository":{"url":"git+https://github.com/breakingthecloud/styrr.git","type":"git"},"_npmVersion":"10.8.2","description":"Styrr multi-model fallback as a Strands Agents SDK Model provider.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@carloscortezcloud/styrr-llm":"^0.4.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0","@strands-agents/sdk":"^1.11.2"},"peerDependencies":{"@strands-agents/sdk":"^1.11.0"},"_npmOperationalInternal":{"tmp":"tmp/styrr-strands_0.1.0_1785289263507_0.8010769348757742","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@carloscortezcloud/styrr-strands","version":"0.1.1","description":"Styrr multi-model fallback as a Strands Agents SDK Model provider.","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"keywords":["strands","styrr","llm","fallback","model-provider"],"license":"Apache-2.0","repository":{"type":"git","url":"git+https://github.com/breakingthecloud/styrr.git"},"dependencies":{"@carloscortezcloud/styrr-llm":"^0.5.0"},"peerDependencies":{"@strands-agents/sdk":"^1.11.0"},"devDependencies":{"@strands-agents/sdk":"^1.11.2","typescript":"^5.5.0"},"type":"module","_id":"@carloscortezcloud/styrr-strands@0.1.1","gitHead":"68ecde68b5c8254e63d9abf3ffd026a00d70024a","bugs":{"url":"https://github.com/breakingthecloud/styrr/issues"},"homepage":"https://github.com/breakingthecloud/styrr#readme","_nodeVersion":"22.23.1","_npmVersion":"10.9.8","dist":{"integrity":"sha512-Km5ViJAweSiRk5PJQcolsBKFv9Z6DrPvBD+mTtU+oNwHirfIMZBzOrDBqzZZAmypuMmaqh6wyMB2MdlWgwSC7g==","shasum":"fcccd25ed49335e395a5cf51c76d988964caf7da","tarball":"https://registry.npmjs.org/@carloscortezcloud/styrr-strands/-/styrr-strands-0.1.1.tgz","fileCount":6,"unpackedSize":14681,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDSGZlnQTSK1jmLo55KPsIEHRxwKi1424hec06BOSE8fgIhAIiIWDaO67te+oaWULXLbaPJJWM8l5SgE34RmVro0y4O"}]},"_npmUser":{"name":"carloscortezcloud","email":"carlos@cortez.cloud"},"directories":{},"maintainers":[{"name":"carloscortezcloud","email":"carlos@cortez.cloud"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/styrr-strands_0.1.1_1785706856894_0.27985497322640307"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-29T01:41:03.285Z","modified":"2026-08-02T21:40:57.187Z","0.1.0":"2026-07-29T01:41:03.644Z","0.1.1":"2026-08-02T21:40:57.026Z"},"bugs":{"url":"https://github.com/breakingthecloud/styrr/issues"},"license":"Apache-2.0","homepage":"https://github.com/breakingthecloud/styrr#readme","keywords":["strands","styrr","llm","fallback","model-provider"],"repository":{"type":"git","url":"git+https://github.com/breakingthecloud/styrr.git"},"description":"Styrr multi-model fallback as a Strands Agents SDK Model provider.","maintainers":[{"name":"carloscortezcloud","email":"carlos@cortez.cloud"}],"readme":"# @carloscortezcloud/styrr-strands\n\nMulti-model fallback as a [Strands Agents SDK](https://www.strands.ai) `Model` provider.\n\nNever crash because a single model is rate-limited or down — Styrr chains models in order and falls through automatically.\n\n## Install\n\n```bash\nnpm install @carloscortezcloud/styrr-llm @carloscortezcloud/styrr-strands\n```\n\nRequires `@strands-agents/sdk` >=1.11.0 as a peer dependency.\n\n## Quick Start\n\n```typescript\nimport { Agent } from '@strands-agents/sdk';\nimport { StyrModelProvider } from '@carloscortezcloud/styrr-strands';\n\nconst agent = new Agent({\n  model: new StyrModelProvider({\n    models: [\n      { id: 'anthropic/claude-sonnet-4-20250514' },\n      { id: 'openai/gpt-4o-mini' },\n    ],\n    apiKey: process.env.OPENROUTER_API_KEY!,\n  }),\n  systemPrompt: 'You are a helpful assistant.',\n});\n```\n\n## Configuration\n\n```typescript\ninterface StyrModelProviderConfig {\n  models:      { id: string; baseUrl?: string; apiKey?: string }[];\n  apiKey:      string;\n  baseUrl?:    string;                        // default: https://openrouter.ai/api/v1\n  onFallback?: (from: string, error: string, next: string) => void;\n}\n```\n\n### Fallback chain\n\nModels are tried in order. If the first returns 429, 5xx, or times out, the next is tried automatically.\n\n```typescript\nconst model = new StyrModelProvider({\n  models: [\n    { id: 'anthropic.claude-sonnet-4-5-v1:0' },    // Bedrock primary\n    { id: 'openai/gpt-4o-mini' },                   // OpenRouter fallback\n    { id: 'nvidia/nemotron-3-super-120b:free' },    // Free fallback\n  ],\n  apiKey: process.env.OPENROUTER_API_KEY!,\n  onFallback: (from, error, next) => {\n    console.warn(`Fell back from ${from} to ${next}: ${error}`);\n  },\n});\n```\n\n### Tools (function calling)\n\nPass tools via the Agent config — tool schemas are forwarded to the LLM automatically.\n\n```typescript\nconst agent = new Agent({\n  model: new StyrModelProvider({\n    models: [{ id: 'openai/gpt-4o-mini' }],\n    apiKey: process.env.OPENROUTER_API_KEY!,\n  }),\n  tools: [{\n    name: 'get_weather',\n    description: 'Get current weather for a location',\n    inputSchema: {\n      type: 'object',\n      properties: { location: { type: 'string' } },\n      required: ['location'],\n    },\n  }],\n  systemPrompt: 'You are a helpful assistant.',\n});\n```\n\n## Stream Lifecycle\n\n`StyrModelProvider.stream()` maps Styrr stream events to the Strands `ModelStreamEvent` lifecycle:\n\n| Styrr event | Strands event(s) |\n|---|---|\n| `text_delta` | `modelContentBlockStartEvent` → 1+ `modelContentBlockDeltaEvent` → `modelContentBlockStopEvent` |\n| `tool_call_start` / `tool_call_done` | `modelContentBlockStartEvent(toolUseStart)` → `modelContentBlockDeltaEvent(toolUseInputDelta)` → `modelContentBlockStopEvent` |\n| `done` | `modelMessageStopEvent` + `modelMetadataEvent` |\n| `error` | `modelMessageStopEvent` (graceful close) |\n\n## API\n\n### `StyrModelProvider`\n\nExtends `Model<StyrModelProviderConfig>`. Implements `stream()` for Strands Agent compatibility.\n\n| Method | Returns | Description |\n|---|---|---|\n| `stream(messages, options?)` | `AsyncIterable<ModelStreamEvent>` | Streaming model call |\n| `updateConfig(config)` | `void` | Merge new config, recreate router |\n| `getConfig()` | `StyrModelProviderConfig` | Return current config |\n| `modelId` | `string \\| undefined` | First model ID |\n\n## Why styrr-strands instead of Strands SDK directly?\n\nThe Strands SDK lets you configure a single model provider (OpenAI, Anthropic, etc.). If that provider returns a 429 (rate-limited) or 5xx, the whole request fails.\n\n`StyrModelProvider` wraps **Styrr's multi-model fallback** behind the same `Model` interface:\n\n| Capability | Strands SDK (direct) | Styrr + Strands |\n|---|---|---|\n| Single provider | ✅ Uses one model | ✅ Uses one model |\n| Fallback on 429/5xx | ❌ Request fails | ✅ Auto-retries next model in chain |\n| Cross-provider fallback | ❌ Tied to one API | ✅ Bedrock → OpenRouter → local in one config |\n| Retry logic | ❌ Manual | ✅ Built-in with configurable retries |\n| Observable fallbacks | ❌ | ✅ `onFallback` hook |\n| Stream lifecycle | ✅ Native | ✅ Full `ModelStreamEvent` mapping |\n| Tool calling | ✅ Native | ✅ Forwarded through Styrr |\n\n**Concrete example**: You deploy with Claude Sonnet on Bedrock as primary, GPT-4o-mini on OpenRouter as fallback, and a free model as third resort. If Bedrock is down, the request transparently falls through — your Strands Agent never knows.\n\n## Architecture\n\n```\nStrands Agent\n  └─ StyrModelProvider  (@carloscortezcloud/styrr-strands)\n       └─ StyrRouter    (@carloscortezcloud/styrr-llm)\n            ├─ OpenAI-compatible provider\n            ├─ AWS Bedrock provider\n            └─ HuggingFace provider (via Inference Endpoints)\n```\n\n`styrr-strands` is a thin adapter layer: it converts Strands `Message[]` → Styrr format, calls `StyrRouter.stream()`, and maps events back to `ModelStreamEvent`.\n\n## Running Tests\n\nTests are in `examples/strands-agent/`:\n\n```bash\ncd examples/strands-agent\npnpm install\npnpm test\n```\n\n## License\n\nApache-2.0\n","readmeFilename":"README.md"}