在 Solon AI 中， Prompt 不仅仅是一个简单的消息集合，还是一个具备感知能力的“执行上下文”。通过 attrs（属性）机制，开发者可以为 AI 的执行过程注入动态参数与运行时资源，这是构建工业级 Agent 的核心基础。


### 1、Prompt  及运行时属性

Prompt 接口通过 attrs() 提供了一个全生命周期的属性桶（Attribute Bucket）。与传统的静态元数据（Metadata）不同，attrs 专为运行态设计：


* **动态性：** 支持挂载 `ChatSession`（有状态会话）、业务拦截器状态、或数据库连接等动态对象。
* **本地化隔离：** `attrs` 中的数据仅在后端流转，不参与提示词染色。这意味着你可以放心地放入 `user_id`、`role_level` 等敏感业务属性，而不用担心它们被泄露给远端大模型。
* **语义萃取：** 提供了 `getUserContent()` 逆序查找算法。它能穿透多轮对话的噪音，精准定位用户最后一次输入的有效意图，确保 Skill 的判断始终基于当前的最新上下文。




接口参考：


```java
public interface Prompt {
    /**
     * 获取属性
     *
     * @since 3.8.4
     */
    Map<String, Object> attrs();

    /**
     * 获取属性
     *
     * @since 3.8.4
     */
    default Object attr(String key) {
        return attrs().get(key);
    }

    /**
     * 获取属性
     *
     * @since 3.8.4
     */
    default <T> T attrAs(String key) {
        return (T) attrs().get(key);
    }

    /**
     * 获取属性
     *
     * @since 3.8.4
     */
    default <T> T attrOrDefault(String key, T def) {
        return (T) attrs().getOrDefault(key, def);
    }

    /**
     * 设置属性
     */
    default Prompt attrPut(String name, Object value) {
        attrs().put(name, value);
        return this;
    }

    /**
     * 设置属性
     */
    default Prompt attrPut(Map<String, Object> map) {
        if (Assert.isNotEmpty(map)) {
            attrs().putAll(map);
        }

        return this;
    }

    /**
     * 获取消息
     */
    List<ChatMessage> getMessages();

    /**
     * 获取首条消息
     *
     * @since 3.8.4
     */
    ChatMessage getFirstMessage();

    /**
     * 获取最后消息
     *
     * @since 3.8.4
     */
    ChatMessage getLastMessage();

    /**
     * 获取用户消息内容
     *
     * @since 3.8.4
     */
    String getUserContent();

    /**
     * 获取系统消息内容
     *
     * @since 3.8.4
     */
    String getSystemContent();

    /*
     * 添加消息
     */
    Prompt addMessage(String msg);

    /*
     * 添加消息
     */
    Prompt addMessage(ChatMessage... msgs);

    /*
     * 添加消息
     */
    Prompt addMessage(Collection<ChatMessage> msgs);

    /*
     * 替换消息
     */
    Prompt replaceMessages(Collection<ChatMessage> messages);

    /**
     * 是否为空
     *
     * @since 3.8.4
     */
    boolean isEmpty();

    /**
     * 是否为空
     */
    static boolean isEmpty(Prompt prompt) {
        return prompt == null || prompt.isEmpty();
    }

    /**
     * 构建
     */
    static Prompt of(Collection<ChatMessage> messages) {
        return new PromptImpl().addMessage(messages);
    }

    /**
     * 构建
     */
    static Prompt of(String message) {
        return new PromptImpl().addMessage(message);
    }

    /**
     * 构建
     */
    static Prompt of(ChatMessage... messages) {
        return new PromptImpl().addMessage(messages);
    }
}
```


### 2、动态赋能：基于业务上下文的 Skill 决策逻辑


基于 Prompt 的属性机制，Skill 获得了超越普通工具（Tool）的“工程智力”，主要体现在以下三个维度：


#### A. 环境感知的准入检查 (isSupported)


Skill 可以通过 `Prompt.attr()` 实时感知业务环境，实现动态唤醒：

* 权限管控：只有当 `attr("role")` 为管理员时，才激活“系统管理技能”。
* 状态过滤：根据 `attr("step")` 的进度，动态决定当前是否应该唤醒某个特定环节的技能包。




#### B. 运行时资源共享 (onAttach)

Skill 可以在执行生命周期内操作 `Prompt` 的属性，实现黑板模式的协作：

* 上下文补全：在 Skill 被附着（Attach）时，根据 `attrs` 中的用户信息，预先从数据库加载业务背景存入 `attrs`。
* 信息共享：多个协同的 Skill 之间可以通过修改 `attrs` 共享中间计算结果，避免重复查库或重复计算。


#### C. 指令的动态增强 (getInstruction)

Skill 不再提供死板的提示词，而是可以根据属性动态生成。

* 个性化偏好：读取 attr("language_style")，动态调整注入给大模型的 System Instruction，实现一套代码适配万千租户的业务规约。

### 3、代码实战：多租户权限“动态”感知技能

在这个示例中，我们实现一个“订单管理专家”技能。它会根据 `attrs` 里的租户 ID 锁定数据范围，并根据用户角色决定是否开放“取消订单”的工具。


```java
public class OrderManagerSkill implements Skill {
    
    @Override
    public boolean isSupported(Prompt prompt) {
        // 1. 语义检查：用户当前意图是否与“订单”相关（逆序获取最新意图）
        boolean isOrderTask = prompt.getUserContent().contains("订单");
        
        // 2. 环境检查：必须持有合法的租户 ID 属性才能激活
        boolean hasTenant = prompt.attr("tenant_id") != null;
        
        return isOrderTask && hasTenant;
    }

    @Override
    public String getInstruction(Prompt prompt) {
        // 3. 动态指令：从 attrs 获取租户名，注入隔离指令
        // 这样模型就知道它只能处理该租户的数据，而不需要前端在 Prompt 里写明
        String tenantName = prompt.attrOrDefault("tenant_name", "未知租户");
        return "你现在是[" + tenantName + "]的订单主管。请只处理该租户下的订单数据，禁止跨租户查询。";
    }

    @Override
    public Collection<FunctionTool> getTools(Prompt prompt) {
        List<FunctionTool> tools = new ArrayList<>();
        
        // 基础查询工具（所有激活技能的用户都有）
        tools.add(new OrderQueryTool());
        
        // 4. 权限隔离：只有属性中标记为 ADMIN 的用户，才动态挂载“取消订单”工具
        if ("ADMIN".equals(prompt.attr("user_role"))) {
            tools.add(new OrderCancelTool());
        }
        
        return tools;
    }
}
```