# `Jido.AI.Skill.ResourceProvider`
[🔗](https://github.com/agentjido/jido_ai/blob/v2.4.0/lib/jido_ai/skill/resource_provider.ex#L1)

Invokes and validates host callbacks that provide runtime skill resources.

Providers are only used for runtime specs supplied through Agent Skills
integration. Filesystem skills continue to use `Jido.AI.Skill.Resources`.

Supported provider forms are:

- `fn request, context -> result end`
- `{Module, :function}`
- `{Module, :function, extra_args}`

Providers receive canonical requests:

    %{operation: :list, skill: spec, policy: policy}
    %{operation: :load, skill: spec, resource_id: resource_id, policy: policy}

Valid results are:

    {:ok, %{resources: [%{id: id, name: name, size: size}], complete: boolean()}}
    {:ok, %{resource_id: resource_id, content: text, size: non_neg_integer()}}
    {:error, term()}

List entries require `id`, `name`, and `size`. Optional fields are `type`,
`modified`, `mime_type`, and `metadata`. The `resources` field is the complete
aggregate listing. `scripts`, `references`, and `assets` are filtered views of
the same entries, so entries intentionally appear in both the aggregate list
and their typed view. IDs are scoped to the activated skill and provider
binding. Loading by an ID that was not present in the activated post-policy
listing is rejected before the provider is called, including when the provider
reported an incomplete listing.

Jido validates and normalizes every result, reapplies `ResourcePolicy`, rejects
entries that cannot be encoded for listing, rejects malformed identifiers and
binary content unless explicitly allowed, and invokes the provider on every resource load so content
remains fresh. Listing truncation is ordered: the first entry that violates
count, declared-size, or encoded-listing limits is excluded, as is everything
after it. Resource IDs are opaque and are never parsed, normalized, joined,
sorted, or interpreted.

# `binding`

```elixir
@type binding() :: %{provider: provider(), context: map()}
```

# `provider`

```elixir
@type provider() ::
  (map(), map() -&gt; term()) | {module(), atom()} | {module(), atom(), [term()]}
```

# `resource_info`

```elixir
@type resource_info() :: %{
  :id =&gt; String.t(),
  :name =&gt; String.t(),
  :size =&gt; non_neg_integer(),
  :modified =&gt; DateTime.t(),
  optional(:type) =&gt; atom() | String.t() | nil,
  optional(:mime_type) =&gt; String.t() | nil,
  optional(:metadata) =&gt; map()
}
```

# `resource_listing`

```elixir
@type resource_listing() :: %{
  resources: [resource_info()],
  scripts: [resource_info()],
  references: [resource_info()],
  assets: [resource_info()],
  complete: boolean(),
  truncated: boolean(),
  truncation_reasons: [atom()],
  limits: map()
}
```

# `list`

```elixir
@spec list(
  provider(),
  Jido.AI.Skill.Spec.t(),
  Jido.AI.Skill.ResourcePolicy.t(),
  map()
) ::
  {:ok, resource_listing()} | {:error, term()}
```

Lists provider-backed resources with opaque IDs.

# `load`

```elixir
@spec load(
  provider(),
  Jido.AI.Skill.Spec.t(),
  String.t(),
  Jido.AI.Skill.ResourcePolicy.t(),
  map()
) ::
  {:ok, Jido.AI.Skill.Resources.loaded_resource()} | {:error, term()}
```

Loads one provider-backed resource by opaque ID.

Binary responses require `binary: :allow`, `filename`, and `mime_type`.

# `validate`

```elixir
@spec validate(provider() | nil) :: {:ok, provider() | nil} | {:error, term()}
```

Validates a provider form.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
