diff --git a/apps/desktop/build/generated-icon.icon/Assets/border.svg b/apps/desktop/build/generated-icon.icon/Assets/border.svg
new file mode 100644
index 00000000000..fb9d4f8c789
--- /dev/null
+++ b/apps/desktop/build/generated-icon.icon/Assets/border.svg
@@ -0,0 +1,3 @@
+
diff --git a/apps/desktop/build/generated-icon.icon/Assets/logo.png b/apps/desktop/build/generated-icon.icon/Assets/logo.png
new file mode 100644
index 00000000000..6fce2046095
Binary files /dev/null and b/apps/desktop/build/generated-icon.icon/Assets/logo.png differ
diff --git a/apps/desktop/build/generated-icon.icon/icon.json b/apps/desktop/build/generated-icon.icon/icon.json
new file mode 100644
index 00000000000..f53f60fc7e4
--- /dev/null
+++ b/apps/desktop/build/generated-icon.icon/icon.json
@@ -0,0 +1,33 @@
+{
+ "fill": {
+ "solid": "srgb:1.00000,1.00000,1.00000,1.00000"
+ },
+ "groups": [
+ {
+ "layers": [
+ {
+ "image-name": "logo.png",
+ "is-glass": false,
+ "name": "Sim"
+ },
+ {
+ "image-name": "border.svg",
+ "is-glass": false,
+ "name": "Dev Border"
+ }
+ ],
+ "shadow": {
+ "kind": "neutral",
+ "opacity": 0
+ },
+ "specular": false,
+ "translucency": {
+ "enabled": false,
+ "value": 0
+ }
+ }
+ ],
+ "supported-platforms": {
+ "squares": ["macOS"]
+ }
+}
diff --git a/apps/sim/.env.example b/apps/sim/.env.example
index ef123188499..3c2dcf8f229 100644
--- a/apps/sim/.env.example
+++ b/apps/sim/.env.example
@@ -63,7 +63,11 @@ API_ENCRYPTION_KEY=your_api_encryption_key # Use `openssl rand -hex 32` to gener
# VLLM_API_KEY= # Optional bearer token if your vLLM instance requires auth
# LITELLM_BASE_URL=http://localhost:4000 # Base URL for your LiteLLM proxy (OpenAI-compatible)
# LITELLM_API_KEY= # Optional bearer token if your LiteLLM proxy requires auth
-# FIREWORKS_API_KEY= # Optional Fireworks AI API key for model listing
+# NEXT_PUBLIC_FORCE_HOSTED=true # Dev only: treat this instance as hosted Sim (sim-auto pool, platform keys); ignored in production builds
+# FIREWORKS_API_KEY= # Optional Fireworks AI API key for model listing and inference
+# FIREWORKS_API_KEY_1= # Optional Fireworks API key for rotation (hosted deployments)
+# FIREWORKS_API_KEY_2= # Additional Fireworks API key for load balancing
+# FIREWORKS_API_KEY_3= # Additional Fireworks API key for load balancing
# NEXT_PUBLIC_BEDROCK_DEFAULT_CREDENTIALS=true # Set when using AWS default credential chain (IAM roles, ECS task roles, IRSA). Hides credential fields in Agent block UI.
# AZURE_OPENAI_ENDPOINT= # Azure OpenAI endpoint (hides field in UI when set alongside NEXT_PUBLIC_AZURE_CONFIGURED)
# AZURE_OPENAI_API_KEY= # Azure OpenAI API key
diff --git a/apps/sim/app/api/providers/fireworks/models/route.ts b/apps/sim/app/api/providers/fireworks/models/route.ts
index ef3c000d960..82754eb53fb 100644
--- a/apps/sim/app/api/providers/fireworks/models/route.ts
+++ b/apps/sim/app/api/providers/fireworks/models/route.ts
@@ -10,6 +10,7 @@ import { validationErrorResponse } from '@/lib/api/server'
import { getBYOKKey } from '@/lib/api-key/byok'
import { getSession } from '@/lib/auth'
import { env } from '@/lib/core/config/env'
+import { isHosted } from '@/lib/core/config/env-flags'
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils'
import { filterBlacklistedModels, isProviderBlacklisted } from '@/providers/utils'
@@ -54,7 +55,13 @@ export const GET = withRouteHandler(async (request: NextRequest) => {
}
}
- if (!apiKey) {
+ /**
+ * On hosted Sim the platform key is the sim-auto pool's inference key, not a
+ * workspace credential: enumerating the whole Fireworks catalog from it would
+ * offer every serverless model as selectable when no key can actually run it
+ * (`getApiKeyWithBYOK` serves the platform key to catalog models only).
+ */
+ if (!apiKey && !isHosted) {
apiKey = env.FIREWORKS_API_KEY
}
diff --git a/apps/sim/blocks/blocks/agent.ts b/apps/sim/blocks/blocks/agent.ts
index fb2e9756c38..29619bff5b7 100644
--- a/apps/sim/blocks/blocks/agent.ts
+++ b/apps/sim/blocks/blocks/agent.ts
@@ -20,6 +20,7 @@ import {
getReasoningEffortValuesForModel,
getThinkingLevelsForModel,
getVerbosityValuesForModel,
+ isAutoModel,
supportsTemperature,
} from '@/providers/models'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
@@ -522,7 +523,13 @@ Return ONLY the JSON array.`,
if (!model) {
throw new Error('No model selected')
}
- const tool = getBaseModelProviders()[model]
+ // sim-auto resolves to a concrete pool model at execution time, where
+ // the agent handler derives the provider from the resolved model and
+ // never reads this serialized value. Serialization still needs the
+ // same provider-id shape every other model stores, so look up the
+ // runtime fallback model's provider.
+ const lookupModel = isAutoModel(model) ? 'claude-sonnet-5' : model
+ const tool = getBaseModelProviders()[lookupModel]
if (!tool) {
throw new Error(`Invalid model selected: ${model}`)
}
diff --git a/apps/sim/blocks/utils.test.ts b/apps/sim/blocks/utils.test.ts
index bf90c25d656..9d5a3adf24f 100644
--- a/apps/sim/blocks/utils.test.ts
+++ b/apps/sim/blocks/utils.test.ts
@@ -40,6 +40,8 @@ vi.mock('@/providers/models', () => ({
getProviderModels: mockGetProviderModels,
getProviderIcon: mockGetProviderIcon,
getBaseModelProviders: mockGetBaseModelProviders,
+ SIM_AUTO_MODEL_ID: 'sim-auto',
+ isAutoModel: (model: string) => model.trim().toLowerCase() === 'sim-auto',
}))
vi.mock('@/providers/utils', () => ({
diff --git a/apps/sim/blocks/utils.ts b/apps/sim/blocks/utils.ts
index f0c7d11f13a..848b8d36363 100644
--- a/apps/sim/blocks/utils.ts
+++ b/apps/sim/blocks/utils.ts
@@ -1,4 +1,5 @@
import { toError } from '@sim/utils/errors'
+import { SimAutoIcon } from '@/components/icons'
import {
isAzureConfigured,
isCohereConfigured,
@@ -14,7 +15,9 @@ import {
getModelSunsetStatus,
getProviderIcon,
getProviderModels,
+ isAutoModel,
orderModelIdsByReleaseDate,
+ SIM_AUTO_MODEL_ID,
} from '@/providers/models'
import { isPiSupportedModel } from '@/providers/pi-providers'
import { getProviderFromModel } from '@/providers/utils'
@@ -75,12 +78,21 @@ export function getModelOptions() {
])
)
- return allModels
+ const options = allModels
.filter((model) => getModelSunsetStatus(model) !== 'deprecated')
.map((model) => {
const icon = getProviderIcon(model)
return { label: model, id: model, ...(icon && { icon }) }
})
+
+ // Hosted-only automatic model. Deliberately LAST in the list (limited
+ // visibility for the initial release): available to anyone who scrolls or
+ // searches for it, but never the first thing the dropdown offers.
+ if (isHosted) {
+ options.push({ label: 'Auto', id: SIM_AUTO_MODEL_ID, icon: SimAutoIcon })
+ }
+
+ return options
}
/**
@@ -183,6 +195,11 @@ function shouldRequireApiKeyForModel(model: string): boolean {
const normalizedModel = model.trim().toLowerCase()
if (!normalizedModel) return false
+ // On hosted Sim the auto pseudo-model resolves server-side to a hosted pool
+ // model. On self-hosted it exists only via imported workflows and always
+ // falls back to the default Anthropic model, so the key field must show.
+ if (isAutoModel(normalizedModel)) return !isHosted
+
if (isHosted) {
const hostedModels = getHostedModels()
if (hostedModels.some((m) => m.toLowerCase() === normalizedModel)) return false
diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx
index efedba2000d..5a2e8424b26 100644
--- a/apps/sim/components/icons.tsx
+++ b/apps/sim/components/icons.tsx
@@ -7558,6 +7558,31 @@ export function SixtyfourIcon(props: SVGProps) {
)
}
+/**
+ * The "sim" brand wordmark (v1.0 brand guide simLogotype paths — the same mark
+ * the navbar/login header renders), inked with the theme-adaptive
+ * `--text-body`. Used as the icon for the Auto model option; the wide viewBox
+ * letterboxes itself inside square icon slots.
+ */
+export function SimAutoIcon(props: SVGProps) {
+ return (
+
+ )
+}
+
export function SimTriggerIcon(props: SVGProps) {
return (