Two ways to add a provider
A provider that can be launched in its own terminal UI and described by flags does not need Rust: write a JSON provider manifest. A provider that needs real logic gets a compiled adapter built on the SDK.
Import through the SDK
Adapter authors depend on uuldana-provider-sdk, which re-exports the adapter-facing subset of the core. Runtime code depends on uuldana-core directly.
For an adapter inside the existing Cargo workspace, the documented dependency is:
[dependencies]
uuldana-provider-sdk.workspace = trueThis is a workspace declaration, not a registry installation instruction. The workspace disables publishing.
use uuldana_provider_sdk::prelude::*;crates/uuldana-provider-sdk/examples/minimal_adapter.rs is a complete adapter in about eighty lines. Run it with cargo run -p uuldana-provider-sdk --example minimal_adapter.
Adapter lifecycle
descriptor -> detect -> capabilities -> map_permissions
-> core validate_mapping
-> launch_plan or resume_plan
-> core LaunchPlan::validate
-> runtime execution -> event_decoder -> shutdown_planOptional capture_session and prepare_handoff receive a RunContext with the session, absolute workspace, and run. Default unsupported responses are honest behavior until an integration can establish support.
Provider manifests
Put a JSON manifest in the adapters directory next to config.json. uuldana-cli loads every *.json file there at start.
{
"version": 1,
"id": "my-agent",
"name": "My Agent",
"executables": ["my-agent"],
"version_args": ["--version"],
"version_contains": "my-agent",
"modes": [
{ "approval": "never_ask", "filesystem": "unrestricted", "network": "allowed",
"args": ["--yes"] },
{ "approval": "ask_every_action", "filesystem": "unrestricted", "network": "allowed",
"args": [] }
],
"prompt_args": ["--prompt", "{prompt}"],
"resume_args": ["--resume", "{session}"],
"session_id_args": ["--session-id", "{session}"],
"interrupts": 2,
"limit_phrases": ["quota exhausted"]
}| Field | Meaning |
|---|---|
id |
Provider id used in config.json. Lowercase ASCII, digits, -, _, .. |
executables |
Names to look for on PATH. Script shims (.cmd, .bat, .ps1) are refused; point at the native executable. |
version_args |
Arguments that print the version. Default ["--version"]. |
version_contains |
Text the version output must contain, case-insensitive. |
modes |
Permission behaviors from most to least permissive. Each lists the policy its flags really enforce, the args that select it, and optionally a note. uuldana-cli picks the first mode that stays inside the requested policy, and refuses the entry if none does. |
leading_args |
Arguments that come first on every start, for a program that needs a subcommand before anything else. |
prompt_args |
How to pass a first prompt, with {prompt}. Without it, a handoff to this provider is refused. |
resume_args |
How to resume a native session, with {session}. Without it, resume is unsupported. |
continue_args |
How to continue the latest conversation of the folder without a session id. Without it, that kind of resume is unsupported. |
session_id_args |
How to choose the session id at launch, with {session}. |
interrupts |
How many Ctrl+C presses stop the provider gracefully (1 to 3). Default 1. |
limit_phrases |
Texts the provider prints when its usage limit is reached. A match marks the run as out of quota, inferred from terminal text. |
A manifest never runs code. It names an executable that uuldana-cli launches, so only install manifests you trust. A manifest that cannot be used is reported as adapter not loaded: <file>: <reason>, and a duplicate id is refused. See examples/adapters/my-agent.json.
Version compatibility
The frozen provider contract is 0.2. While the major version is zero, minor versions must match exactly during registration. A changed frozen interface needs a written reason, a version bump, and checks of dependent implementations.
Public enums that may grow are non-exhaustive. Match with wildcard arms, and use constructors and builders for non-exhaustive request and plan structures.
Authoring obligations
- Preserve the real agent and its native discovery mechanisms.
- Avoid credential reads, native setting writes, and configuration-directory overrides.
- Report effective permission behavior honestly and launch with validated policy only.
- Treat unknown capabilities as unknown.
- Decode malformed input without panicking, and label fidelity accurately.
- Preserve native session identity changes without inventing lineage.