Skip to content

Dependencies & Repositories

Dependencies are reusable artifacts — repositories, component definitions, pre-defined action chains, or device services — declared in a module’s dependencies array. All dependencies are initialized when the module is decoded.

"dependencies": [
{ "repository": { "remote": { "id": "repo_api", "config": { "endPoint": "https://..." } } } },
{ "repository": { "local": { "id": "repo_local", "config": {} } } },
{ "repository": { "secured": { "id": "repo_keys", "config": {} } } },
{ "repository": { "firebase": { "id": "repo_fb", "config": { "collectionPath": "apps/app_id" } } } },
{ "component": { "id": "my_template", "type": "vstack", ... } },
{ "action": { "repo": { "id": "my_shared_action", ... } } },
{ "service": { "audio": { "id": "audio_service_id" } } },
{ "service": { "push": { "id": "push_service_id" } } }
]

ℹ Note: Ordering matters: a dependency MAY only reference dependencies declared earlier in the same array.

"repositoryId": "repo_api" // In a repo action
"_source": "dp://my_template" // In a template _source
"serviceId": "audio_service_id" // In a service action
"dependencyId": "repo_fb" // In a listen action

Repositories expose four CRUD operations: create, read, update, delete. HTTP mapping for remote: create=POST, read=GET, update=PUT/PATCH, delete=DELETE.

Repository and service kinds are open strings. A runtime resolves a kind against a host-populated registry; a kind listed in this table means the language defines its contract, not that every runtime ships it. Hosts register custom kinds under their own key and SHOULD prefix the key so it cannot collide with a kind defined by a later revision of this specification.

KindDescriptionconfig fields
remoteNetwork-backed REST repository.endPoint (required): base URL string. interceptor (optional): see §5.4.
localDocument-oriented local JSON storage. Persists across app sessions.No required fields. Pass config: {}.
securedSecure key/value store (platform keychain) for secrets and tokens.No required fields. Pass config: {}.
firebaseRealtime backend integration. Designed for use with the listen action.collectionPath: root path in the Firebase project.
photosDevice photo library access. Presents a native picker UI on read.No required fields. Pass config: {}.
aiHost-provided AI provider. The host injects the endpoint, credentials, and model routing; modules never carry AI credentials or provider URLs. Target of the ai action’s input.provider for host-managed inference (§10.11).No required fields. Pass config: {}.

Neither official runtime ships firebase or ai as a built-in; the ai kind is host-provided. See each runtime’s README for its built-in set.

Storage partition. A host MAY pass a storage namespace when it validates a module. local and secured stores open inside that partition. When no namespace is passed, they open in a layout shared by every un-namespaced module and keyed by repository id alone, so two modules declaring the same repository id share one store. Hosts that render more than one module SHOULD pass a stable namespace per module.

photos repository — operations and params

OperationPurposeparams fields
readOpen the native photo picker. On success, the output context key receives an array of the selected photo file:// URLs — one element per selection, [] if cancelled — for any selectionLimit. Unwrap a single pick with first(...) or [0]; each URL is usable directly as a media/image source.selectionLimit (number, default 1): maximum photos the user can select. mediaTypes (array of strings): filter by "image" and/or "video".
createSave a photo URL to the device library.url (string/expr): the image URL to save.
deleteDelete a photo from the device library by its asset identifier.assetIdentifier (string/expr): platform-native asset ID returned by a previous read.
"dependencies": [
{ "repository": { "photos": { "id": "photos", "config": {} } } }
]
{
"repo": {
"id": "pick_single_action_id",
"repositoryId": "photos",
"operation": "read",
"params": {
"selectionLimit": 1,
"mediaTypes": ["image"]
}
},
"output": {
"success": [
{ "state": { "id": "set_photo", "input": { "photoURL": "@{pick_single_action_id}" } } }
]
}
}

Remote repositories support an interceptor that reads one or more tokens from a secured repository and injects them into request headers automatically.

{ "repository": { "remote": {
"id": "repo_openai",
"config": {
"endPoint": "https://api.openai.com/v1/responses",
"interceptor": {
"adapter": {
"operations": [
{ "kind": "setBearerToken", "repositoryId": "repo_keys", "key": "openai_token" }
]
},
"retrier": { "maxRetries": 3, "retryDelay": 1.0 }
}
} } }
Interceptor fieldDescription
adapter.operationsArray of operation objects applied in order to every outgoing request.
adapter.operations[].kindOperation kind: setHeader (named header), setBearerToken (Authorization: Bearer ), setQueryParam (URL query parameter).
adapter.operations[].fieldTarget header name or query param name. Required for setHeader and setQueryParam.
adapter.operations[].repositoryIdID of a secured repository to read the token value from. Mutually exclusive with value.
adapter.operations[].keyKey to look up in the repository. Required when repositoryId is set.
adapter.operations[].valueStatic string value to inject directly. Mutually exclusive with repositoryId/key.
retrier.maxRetriesMaximum retry attempts on transient failures. Default: 3.
retrier.retryDelayDelay in seconds between retries. Default: 1.0. Retries on: serviceUnavailable, internalServer, noConnection, timeout.

Services expose device or platform capabilities. Declare them in the dependencies array and invoke them via the service action.

Service kinds are open strings, resolved the same way as repository kinds (§5.3): the table lists the kinds whose contract this specification defines, and hosts register custom kinds under their own key.

{ "service": { "audio": { "id": "audio_service_id" } } },
{ "service": { "push": { "id": "push_service_id" } } }
Known service kindPurpose
audioPlays sounds and triggers haptic feedback.
pushSchedules local notifications via UNUserNotificationCenter. Does not send remote push notifications.

Reusable component subtrees and pre-defined action chains can be registered as dependencies. Component dependencies are referenced with dp:// from template components. Action dependencies are invoked by their id via the template action kind.