# Resources

> Resources are shared state that systems read and write through typed parameters.

Resources are shared state that systems read and write. Every piece of data a system needs — configuration, conversation history, the output of a previous system — is a resource that the framework injects as a typed parameter.

```rust
use polaris_ai::system::resource::{GlobalResource, LocalResource};
use polaris_ai::system::param::{Res, ResMut};
use polaris_ai::system::system;


#[system]
async fn greet(config: Res<AppConfig>, mut memory: ResMut<ContextManager>) {
    memory.messages.push(format!("Hello from {}", config.agent_name));
}
```

You declare what you need, and the framework provides it. There is no manual lookup, no string keys, and no runtime casting.

## Global and local resources

Resources fall into two categories based on their lifetime and mutability.

**Global resources** live for the lifetime of the server. They are read-only and shared across all execution contexts. Configuration, model registries, and tool registries are typical global resources.

**Local resources** are created fresh for each execution context. They are mutable and isolated, so concurrent agent executions never interfere with each other. Conversation history and loop state are typical local resources.

| Scope  | Marker trait     | Lifetime    | Access                  |
| ------ | ---------------- | ----------- | ----------------------- |
| Global | `GlobalResource` | Server      | `Res<T>` (read-only)    |
| Local  | `LocalResource`  | Per-context | `Res<T>` or `ResMut<T>` |

## Defining resources

A resource is any type that implements a marker trait. For a global resource, implement `GlobalResource`. For a local resource, implement `LocalResource`.

```rust
use polaris_ai::system::resource::{GlobalResource, LocalResource};


struct AppConfig {
    agent_name: String,
    model_id: String,
}


impl GlobalResource for AppConfig {}


struct ContextManager {
    messages: Vec<String>,
}


impl LocalResource for ContextManager {}


impl ContextManager {
    fn new() -> Self {
        Self { messages: Vec::new() }
    }
}
```

The marker traits do not require methods. The marker traits exist only to enforce the access rules at the type level: you cannot accidentally take `ResMut<AppConfig>` on a global resource, and you cannot share a local resource across contexts.

## Registering resources

You register resources on the `Server` before execution starts. Global resources are inserted directly. Local resources are registered with a factory function that produces a fresh instance for each context.

```rust
use polaris_ai::system::server::Server;


let mut server = Server::new();


server.insert_global(AppConfig {
    agent_name: "research-agent".into(),
    model_id: "claude-sonnet-4-20250514".into(),
});


server.register_local(ContextManager::new);
```

Plugins typically handle registration in their `build()` method, so you rarely call these methods directly unless you are writing a plugin or setting up a server by hand.

## Reading resources with Res and ResMut

Systems declare resource dependencies as function parameters. `Res<T>` provides read-only access and walks up the context hierarchy to find the resource — it can reach global resources from any context. `ResMut<T>` provides mutable access but is scoped to the current context only.

```rust
use polaris_ai::system::system;
use polaris_ai::system::param::{Res, ResMut};


#[system]
async fn act(
    config: Res<AppConfig>,
    mut memory: ResMut<ContextManager>,
) -> String {
    let prompt = format!("{}: processing {} messages", config.agent_name, memory.messages.len());
    memory.messages.push(prompt.clone());
    prompt
}
```

Both `Res<T>` and `ResMut<T>` dereference to `T`, so you access fields and methods directly.

## Reading system outputs with Out

When a system returns a value, the next system in the graph can read it with `Out<T>`. The type parameter matches the return type of the preceding system.

```rust
use polaris_ai::system::param::Out;


struct AnalysisResult {
    summary: String,
}


#[system]
async fn analyze(config: Res<AppConfig>) -> AnalysisResult {
    AnalysisResult {
        summary: format!("Analysis by {}", config.agent_name),
    }
}


#[system]
async fn report(result: Out<AnalysisResult>, mut memory: ResMut<ContextManager>) {
    memory.messages.push(result.summary.clone());
}
```

Outputs belong to the current context and do not resolve through parent scopes. `Out<T>` reads the most recently stored output of type `T`, not necessarily the immediately preceding node. Clear stale outputs with `ctx.clear_outputs()` when reusing a context for a new independent turn. Successful execution moves the last output into `ExecutionResult`; it does not clear every typed output slot.

## Error outputs with ErrOut

When a fallible system fails, recovery systems on an error edge can read the error context with `ErrOut<T>`. This is covered in detail in [Error handling and retries](/docs/polaris/advanced-topics/error-handling-and-retries.md).

## Putting it together

Here is a complete example that defines both resource types, registers them, and uses them in systems that form a sequential pipeline.

```rust
use polaris_ai::system::resource::{GlobalResource, LocalResource};
use polaris_ai::system::param::{Res, ResMut, Out};
use polaris_ai::system::server::Server;
use polaris_ai::system::system;


struct AppConfig {
    agent_name: String,
}


impl GlobalResource for AppConfig {}


struct ReactState {
    is_complete: bool,
}


impl LocalResource for ReactState {}


#[system]
async fn initialize(config: Res<AppConfig>) -> String {
    format!("Starting {}", config.agent_name)
}


#[system]
async fn process(
    greeting: Out<String>,
    mut state: ResMut<ReactState>,
) {
    state.is_complete = true;
}


let mut server = Server::new();
server.insert_global(AppConfig { agent_name: "my-agent".into() });
server.register_local(|| ReactState { is_complete: false });
```

The `initialize` system reads the global configuration through `Res<AppConfig>`. The `process` system reads the output of `initialize` through `Out<String>` and mutates the local state through `ResMut<ReactState>`. The global resource is shared and immutable; the local resource is private to this execution context and freely mutable.

For how resources are organized into parent-child scopes, see [Context hierarchies](/docs/polaris/advanced-topics/context-hierarchies.md). For the graph that connects these systems, see [Graphs](/docs/polaris/core-concepts/graphs.md).
