# Roles

A role defines what an agent can do. It has an identity (name, goal and domain) and a set of actions, the `@ActionSpec` methods the framework discovers on the class. The role also builds the system prompt the agent sends to the model. An agent can hold several roles.

## Build a role with `RoleBuilder`

Use `RoleBuilder` to define a role inline, for example in tests, scripts, or when the configuration is loaded at runtime. `create()` takes no arguments, and `.name(...)` sets the name. The builder also sets the model, resilience, input and output guardrails, and programmatic actions (`addAction`).

<!-- java-contract: src/main/java/com/example/tnsai/docs/RolesBuilderExample.java -->
```java
package com.example.tnsai.docs;

import com.tnsai.llm.providers.AnthropicClient;
import com.tnsai.roles.Role;
import com.tnsai.roles.RoleBuilder;

public final class RolesBuilderExample {
    private RolesBuilderExample() {}

    public static Role createResearcher() {
        return RoleBuilder.create()
            .name("Researcher")
            .goal("Find and synthesize information from academic sources")
            .domain("academic-research")
            .llm(new AnthropicClient("claude-sonnet-4-20250514"))
            .build();
    }
}
```

A builder role has no `mustNever` or `mustAlways` constraints, because those live on annotated action methods. For them, subclass `Role`.

## Write a role class

Subclass `Role`, implement `getIdentity()`, and annotate the action methods. `@RoleSpec` on the class carries the rest of the role's configuration: description, domains, goals, the model (`llm`), knowledge and config. Safety constraints go on each action.

<!-- java-contract: src/main/java/com/example/tnsai/docs/RolesSpecExample.java -->
```java
package com.example.tnsai.docs;

import com.tnsai.annotations.ActionSpec;
import com.tnsai.annotations.Goal;
import com.tnsai.annotations.LLMSpec;
import com.tnsai.annotations.RoleSpec;
import com.tnsai.enums.ActionType;
import com.tnsai.models.role.RoleIdentity;
import com.tnsai.roles.Role;

@RoleSpec(
    name = "Researcher",
    description = "Finds and synthesizes academic information",
    domains = {"academic", "research"},
    goals = {
        @Goal(
            name = "find_papers",
            condition = "relevant_papers_found",
            description = "Locate and synthesize relevant research"
        )
    },
    llm = @LLMSpec(provider = LLMSpec.Provider.ANTHROPIC, model = "claude-sonnet-4-20250514")
)
public final class RolesSpecExample extends Role {

    @Override
    public RoleIdentity getIdentity() {
        return new RoleIdentity("Researcher", "Find papers", "academic");
    }

    @ActionSpec(
        type = ActionType.LOCAL,
        description = "Search for academic papers on a topic",
        mustNever = {"fabricate references", "plagiarize content"},
        mustAlways = {"cite sources properly"}
    )
    public String searchPapers(String query) {
        return query;
    }
}
```

A subclass without its own `@RoleSpec` inherits the nearest superclass's. A subclass that declares one replaces the whole specification, and fields are not merged.

For how each action type runs, and how to post-process a result with `ActionResult`, see [Actions](actions.md).

## Inspect a role

These accessors read a role's identity, actions and generated prompts. The per-action constraints are on `ActionMetadata`.

```java
RoleIdentity identity = role.identity();
String name = role.getName();
String goal = role.getGoal();
String domain = role.getDomain();

List<ActionMetadata> actions = role.getActions();
int count = role.getActionCount();
boolean has = role.hasAction("searchPapers");
Optional<ActionMetadata> action = role.getAction("searchPapers");
String[] mustNever = action.map(ActionMetadata::getMustNever).orElse(new String[0]);
String[] mustAlways = action.map(ActionMetadata::getMustAlways).orElse(new String[0]);

String systemPrompt = role.getSystemPrompt();   // identity plus every action and its constraints
String minimalPrompt = role.getMinimalPrompt(); // identity only
```

Two types are named `Capability`. `com.tnsai.capabilities.Capability` is the annotation for [reusable actions](capabilities.md). `com.tnsai.models.agent.Capability` is a model type, and a role does not need it.

## Related

- [Actions](actions.md): action types, the execution pipeline and `ActionResult`.
- [Capabilities](capabilities.md): share actions across roles.
- [Create an agent](create.md): add roles to an agent.
