Skip to main content
Config and Outputs are Pydantic models that define your resource’s interface. Config specifies what users configure, while Outputs defines what your resource exposes to dependent resources.

Config Basics

Config classes inherit from Config, which extends Pydantic’s BaseModel with extra="forbid" to catch typos:
Key behaviors:
  • Unknown fields raise ValidationError (catches typos in YAML)
  • Type coercion is automatic (string "10" becomes int 10)
  • All Pydantic validation features work (Field, validators, etc.)

Outputs Basics

Outputs classes inherit from Outputs with the same extra="forbid" setting:
Outputs are returned from on_create and on_update lifecycle methods. Other resources can reference these fields through the dependency system.

Field Types

Required Fields

Fields without defaults are required:

Optional Fields with Defaults

Provide sensible defaults for common cases:

Optional Fields That May Be Absent

Use None default for truly optional fields:

FieldReference for Dynamic Values

The Field type alias allows config fields to accept either a direct value or a reference to another resource’s output:
Users can provide a direct value:
Or reference another resource’s output:

How FieldReference Works

When the runtime processes a resource, it resolves all FieldReference values before calling your lifecycle methods. By the time on_create runs, self.config.database_url contains the actual string value, not the reference.
You don’t need to handle FieldReference resolution in your code. The runtime resolves all references to their actual values before invoking lifecycle methods.

When to Use Field

Use Field[T] for config values that commonly come from other resources:

Dependency for Whole-Resource Access

When you need access to an entire resource (its config, outputs, and methods) rather than just a single field, use Dependency[T]:

Resolving Dependencies

In your lifecycle methods, call resolve() to get the typed resource instance:
The runtime resolves dependencies before calling your lifecycle handler. The resolve() method returns the pre-resolved instance. If the dependent resource is not yet READY, it will raise a RuntimeError.

YAML Syntax

Users specify whole-resource dependencies without a field key:

Dependency vs FieldReference

Example comparison:

Validation Patterns

Field Constraints

Use Pydantic’s Field function for constraints:
Import Pydantic’s Field as PydanticField to avoid confusion with the SDK’s Field type alias used for FieldReference support.

Field Validators

Validate individual fields with custom logic:

Model Validators

Validate relationships between fields:

Type Coercion

Pydantic automatically coerces compatible types:
For strict typing without coercion, use strict mode on fields:

Output Design Best Practices

Expose What Dependents Need

Think about what downstream resources will need:

Use Consistent Naming

Follow these conventions:

Keep Outputs Stable

Output field names are part of your API. Changing them breaks dependent resources:

Include Sufficient Context

Provide enough information for dependents to work without additional API calls:

Complete Example

Here’s a well-designed Config and Outputs pair:

What’s Next

Lifecycle Methods

Implement on_create, on_update, and on_delete handlers.

Building Providers Overview

Full guide to creating and deploying providers.