# How OpenWork Provisions and Manages Inference Models Across Teams

> Learn how OpenWork provisions and manages inference models as shared, centrally-managed resources. Discover organization tiers, curated model aliases, and custom provider support for seamless AI integration.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: architecture
- Published: 2026-08-01

---

**OpenWork provisions inference models as shared, centrally-managed resources organized by organization tiers, with curated model aliases from OpenRouter and optional custom provider support.**

OpenWork's architecture treats **inference model provisioning** as a core platform capability that ensures each team sees only authorized models while maintaining consistent quota enforcement. This article examines how the system manages the complete lifecycle—from upstream catalog sync to runtime model selection in the UI.

## Understanding the Model Catalog Architecture

OpenWork does not host its own model registry. Instead, it consumes the external **OpenRouter catalog** published at `models.dev`.

The upstream reference is documented directly in the source code:

> "For upstreamModel values, please get from [`models.dev/api.json`](https://github.com/different-ai/openwork/blob/main/models.dev/api.json) provider = `openrouter.models.id`"

This integration lives in [`packages/types/src/den/inference.ts`](https://github.com/different-ai/openwork/blob/main/packages/types/src/den/inference.ts), which serves as the central configuration hub for all inference-related types and constants.

## Model Aliases: Curating the User-Facing Catalog

Raw OpenRouter identifiers like `z-ai/glm-5.2` are not user-friendly. OpenWork solves this through the **`INFERENCE_MODEL_ALIASES`** constant, which maps technical upstream IDs to polished UI labels.

Each alias entry contains four critical fields:

- **`upstreamModel`** — the exact OpenRouter identifier for API calls
- **`displayName`** — what users see in the model picker (e.g., "OpenWork: GLM-5.2")
- **`enabled`** — a kill-switch for rapid model decommissioning
- **`usageFactor`** — the billing/quota multiplier applied to requests

```ts
export const INFERENCE_MODEL_ALIASES = {
  "z-ai/glm-5.2": {
    upstreamModel: "z-ai/glm-5.2",
    displayName: "OpenWork: GLM-5.2",
    enabled: true,
    usageFactor: 1,
  },
  // …additional models…
} as const;

```

[Source](https://github.com/different-ai/openwork/blob/dev/packages/types/src/den/inference.ts)

This abstraction allows OpenWork to swap upstream providers, rename displays, or adjust pricing without changing client code.

## Organization-Level Model Policies

Access control happens at the **organization tier** through `InferenceOrganizationMetadata`. This structure captures:

- **`tier`** — either `tier1` or `tier2`, determining quota ceilings
- **`enabled`** — a master switch for inference capabilities organization-wide

Tier limits are defined in `INFERENCE_TIER_LIMITS` within the same file. When a user's organization changes tiers, the available model set and usage ceilings update automatically—no client redeployment required.

## Runtime Model Provisioning Flow

The actual **model provisioning** unfolds when a user opens the composer interface:

1. The client calls `readAvailableModels()` to fetch the current authorized set
2. The backend intersects: enabled aliases × organization tier limits × custom provider policy
3. The UI renders a picker with `selectable` flag indicating valid choices
4. If a previously-selected model becomes disabled, the picker warns and forces reselection

This behavior is validated in the end-to-end test suite:

```ts
const models = await readAvailableModels(app);
const selectable = models.find(m => m.selectable);
if (!selectable) throw new Error("No selectable model was returned.");

const selected = await selectModel(app, selectable.id);
expect(selected.id).toBe(selectable.id);

```

See [`evals/specs/models-available.slow.test.ts`](https://github.com/different-ai/openwork/blob/main/evals/specs/models-available.slow.test.ts) (lines 221–243) for the complete validation.

## Custom Provider Support for Advanced Teams

Not all teams want to rely solely on OpenWork's curated catalog. The platform supports **bring-your-own-provider** scenarios through a configurable policy in [`desktop-policies.ts`](https://github.com/different-ai/openwork/blob/main/desktop-policies.ts):

```ts
{
  name: "Custom providers",
  description: "Allow users to add and use models that are not deployed through OpenWork Cloud.",
  // …policy implementation…
}

```

[Source](https://github.com/different-ai/openwork/blob/dev/packages/types/src/den/desktop-policies.ts)

When enabled, this policy expands the `availableModels` response to include user-added providers, bypassing the alias system entirely for those entries.

## Quota Management and Reset Strategies

Usage enforcement relies on two mechanisms in [`packages/types/src/den/inference.ts`](https://github.com/different-ai/openwork/blob/main/packages/types/src/den/inference.ts):

- **`INFERENCE_USAGE_CONVERSION_FACTOR`** — normalizes token counts across models with different `usageFactor` values
- **`INFERENCE_RESET_STRATEGY_BY_WINDOW_TYPE`** — determines when counters zero out

Reset windows support three types: `five_hour`, `weekly`, and `monthly`. Each window type maps to either `anchored` (fixed calendar boundaries) or `activity_based` (rolling from last usage) reset behavior. This allows fine-grained control over burst capacity versus sustained throughput.

## Summary

- **OpenWork inference model provisioning** consumes the external OpenRouter catalog but presents a curated, aliased interface to users
- The `INFERENCE_MODEL_ALIASES` constant in [`inference.ts`](https://github.com/different-ai/openwork/blob/main/inference.ts) controls all platform-provided model metadata, enablement, and pricing
- `InferenceOrganizationMetadata` and `INFERENCE_TIER_LIMITS` enforce access boundaries per team
- Runtime selection flows through `readAvailableModels()` with automatic picker updates when policies change
- Custom provider policies in [`desktop-policies.ts`](https://github.com/different-ai/openwork/blob/main/desktop-policies.ts) allow advanced teams to extend beyond the managed catalog
- Quota enforcement combines usage factors with configurable reset strategies across multiple time windows

## Frequently Asked Questions

### How does OpenWork decide which models a team can access?

OpenWork computes available models by intersecting three factors: **globally enabled aliases** from `INFERENCE_MODEL_ALIASES`, the **organization's tier limits** from `INFERENCE_TIER_LIMITS`, and whether **custom providers** are permitted via the desktop policy. The backend returns this computed set through `readAvailableModels()`, and the UI renders only selectable entries.

### Can teams use their own API keys for models not in OpenWork's catalog?

Yes, when the **Custom providers** policy is enabled in [`desktop-policies.ts`](https://github.com/different-ai/openwork/blob/main/desktop-policies.ts). This allows users to add and authenticate against external model providers independent of the OpenWork Cloud deployment. The policy is toggled per-organization, so administrators control which teams have this capability.

### What happens when OpenWork disables a model that a team is actively using?

The next time the user opens the model picker or refreshes available models, the disabled entry will show a **warning state** and become non-selectable. The UI forces selection of a different model before composition can resume. This graceful degradation is validated in the [`models-available.slow.test.ts`](https://github.com/different-ai/openwork/blob/main/models-available.slow.test.ts) e2e suite.

### How does OpenWork calculate usage quotas across different model pricing tiers?

Each model alias carries a **`usageFactor`** that acts as a multiplier on raw token counts. The `INFERENCE_USAGE_CONVERSION_FACTOR` constant normalizes these to a common billing unit. Quotas reset according to `INFERENCE_RESET_STRATEGY_BY_WINDOW_TYPE`, which assigns either anchored (calendar-based) or activity-based (rolling) reset behavior to each window type.