在人工智能代理逐步成为软件开发重要参与者的今天,框架设计面临一个根本性挑战:如何让同一套代码、同一套工具既服务于人类开发者的直觉式编程,又满足 AI Agent 对显式结构化信息的严格需求。Plain 作为一款从 Django 分叉而来的 Python 全栈框架,给出了独特的双模式架构答案。它不只是一个 Web 框架,更是一种面向人类与代理共生的开发范式宣言。

双模式架构的核心设计理念

传统 Web 框架的设计假设使用者是人类开发者,文档、API 设计和错误信息都围绕人类认知模式优化。然而,当 AI Agent 参与代码编写、调试和部署时,这套假设立即失效 ——Agent 需要结构化的类型签名、精确的约束描述以及可枚举的 action 集合。Plain 的核心突破在于从第一天起就将「人类可读」与「机器可解析」视为同一设计的两面,而非两个独立层面。

框架的官方定位清晰表述了这一理念:Explicit, typed, and predictable. What's good for humans is good for agents.(显式、类型化、可预测。对人类友好的特性同样对代理友好。)这一原则贯穿于代码组织、ORM 设计、CLI 工具链乃至文档生成的每个环节。Plain 认为,如果代码对人类足够清晰 —— 严格的类型注解、明确的约束声明、可预测的运行时行为 —— 那么它对 AI Agent 同样易于理解和操作。这种设计哲学消除了传统框架中「人类接口」与「代理接口」的割裂,实现了真正意义上的双模式统一。

Agent Tooling:面向代理的工具链设计

Plain 为 AI Agent 提供了三类核心工具,形成了一个完整的代理工作流支撑体系。

Rules(规则) 是 Plain 项目的内置护栏,存储在项目规则文件中(例如 Claude Code 的 .claude/rules/ 目录)。这些文件通常控制在 50 行左右,针对最常见的开发错误提供即时约束。规则机制确保 Agent 在执行修改时不会绕过关键的业务逻辑约束,例如数据库约束、权限边界或安全检查。这种设计将安全护栏从框架层面下沉到项目层面,让每个团队可以定义自己的代理行为边界。

Docs(文档) 是 Plain 框架的独特创新 —— 全框架文档可以通过命令行按需访问:

plain docs models                      # 完整文档
plain docs models --section querying   # 单节文档
plain docs models --api                # 仅类型签名
plain docs --search "queryset"         # 跨包搜索

这套文档系统的关键在于结构化输出:不仅提供人类可读的说明,还输出 Agent 可解析的 API 签名和约束信息。当 Agent 需要理解某个模型的查询方式时,它可以直接调用 plain docs 获取类型化的方法签名,而非依赖语义理解去解析自然语言文档。

Skills(技能) 是端到端工作流的触发机制,通过斜杠命令激活。它们不是简单的脚本,而是包含上下文收集、决策判断和执行验证的完整流程:

  • /plain-install —— 添加新包并引导完成初始化配置
  • /plain-upgrade —— 版本升级、变更日志阅读、破坏性变更处理、检测执行
  • /plain-optimize —— 性能追踪捕获、慢查询识别、N+1 问题定位与修复
  • /plain-bug —— 上下文收集与 GitHub Issue 自动提交

这些技能的存在使得 Agent 能够以标准化方式执行复杂任务,而非在每次需要时重新发明工作流程。框架团队将多年积累的开发运维经验封装为可复用的技能单元,Agent 调用这些技能时获得的是经过验证的最佳实践。

统一运行时的技术实现

Plain 的双模式架构并非通过两层独立的运行时实现,而是基于同一套 Python 运行时和同一套类型系统完成。这从框架的代码示例中可以清晰看到:

# app/users/models.py
from plain import postgres
from plain.postgres import types
from plain.passwords.models import PasswordField

@postgres.register_model
class User(postgres.Model):
    email: str = types.EmailField()
    password: str = PasswordField()
    display_name: str = types.CharField(max_length=100)
    is_admin: bool = types.BooleanField(default=False)
    created_at: datetime = types.DateTimeField(auto_now_add=True)

    query: postgres.QuerySet[User] = postgres.QuerySet()

    model_options = postgres.Options(
        constraints=[
            postgres.UniqueConstraint(fields=["email"], name="unique_email"),
        ],
    )

这段模型定义对人类开发者而言是直观的 —— 使用类型注解声明字段、装饰器注册模型、选项对象定义约束。对 AI Agent 而言,这些类型注解提供了完整的结构信息,Agent 可以准确知道每个字段的类型、可选参数和约束条件,无需通过尝试错误来推断 API。视图层同样遵循这一原则:

# app/users/views.py
from plain.views import DetailView
from .models import User

class UserDetail(DetailView):
    template_name = "users/detail.html"

    def get_object(self):
        return User.query.get(pk=self.url_kwargs["pk"])

类视图的结构、模板名称的类型化声明、URL 参数的显式提取 —— 每一步都提供了 Agent 可利用的元信息。Plain 的 URL 路由同样采用显式声明:

# app/users/urls.py
from plain.urls import Router, path
from . import views

class UsersRouter(Router):
    namespace = "users"
    urls = [
        path("<int:pk>/", views.UserDetail),
    ]

这种设计确保 Agent 在进行路由注册时可以精确知道路径模式、参数类型和对应的处理视图,无需通过运行时行为推测框架约定。

三十个第一方包与双模式能力的扩展

Plain 框架采用模块化架构,通过 30 个第一方包覆盖从核心框架到生产运维的完整技术栈。这些包并非简单的功能集合,而是按照「人类开发体验」与「代理可操作性」双重标准设计。

后端包(plain.api、plain.jobs、plain.email、plain.cache 等)都提供类型化的公共接口。例如,背景任务包 plain.jobs 不仅暴露人类可理解的调度 API,还提供完整的类型签名,使 Agent 能够精确构造任务参数、处理结果回调并正确处理异常场景。

前端包(plain.htmx、plain.tailwind、plain.elements、plain.pages 等)将 UI 组件的类型信息纳入框架范畴。Agent 不再需要从 HTML 源码中推断组件结构,而是可以直接查询可用元素、属性和事件处理器。

开发运维包(plain.dev、plain.pytest、plain.toolbar、plain.portal、plain.tunnel 等)构建了一个完整的本地开发环境,其中每个工具都可以通过命令行调用并返回结构化输出。这种设计使得 Agent 能够像人类开发者一样使用开发服务器、运行测试、调试问题 —— 使用完全相同的命令和接口。

值得注意的是,plain.code 包提供了 Python、JavaScript、CSS 的统一格式化能力,而 plain.esbuild 处理 JavaScript 打包。Agent 在执行代码修改后,可以调用 plain fix 一次性完成多语言的格式化和 lint 检查,这种统一的修复机制显著降低了代理与人类开发者的协作摩擦。

与传统框架的关键差异

如果将 Plain 与 Django、FastAPI 等主流 Python 框架进行对比,其双模式特征更加清晰。Django 同样拥有完善的 ORM 和管理后台,但其设计完全围绕人类开发者展开 —— 虽然 Django REST Framework 提供了 API 能力,但 API 的可发现性和类型化程度远低于 Plain 的原生设计。FastAPI 依靠类型注解实现了良好的 API 可发现性,但它缺少面向 Agent 的工作流工具(Skills)、项目级护栏(Rules)和按需文档系统。

从 Agent 的视角来看,使用传统框架意味着大量隐式知识需要通过试错或外部文档获取。使用 Plain 时,Agent 可以通过 plain docs --api 直接查询任何包的公共接口,通过项目规则文件理解团队的约束约定,通过 Skills 标准化执行复杂操作。这种设计并非简单地「让框架对 AI 更友好」,而是将双模式能力作为一等公民来设计。

落地到团队的实施考量

对于考虑采用 Plain 的技术团队,有几个关键参数值得关注。首先,Plain 要求 Python 3.13 及以上版本,这对依赖旧版 Python 的存量项目可能构成迁移成本。其次,框架强制使用 PostgreSQL 数据库,对于已有其他数据库投资的项目需要评估迁移工作量。第三,Plain 目前要求使用 uv 作为包管理工具、ruff 作为 linter 和格式化工具、ty 作为类型检查工具 —— 这种 opinionated 的技术栈选择虽然简化了决策,但要求团队接受完整的工具链替换。

在双模式能力落地方面,建议团队重点配置 Rules 文件来定义项目特定的代理行为边界。初始规则集可以从以下维度设计:数据库写操作的审批流程、生产环境部署的确认机制、敏感 API 的调用限制、以及特定文件路径的保护规则。这些规则的粒度应根据团队对代理自治程度的期望来调整 —— 过于宽松会失去护栏意义,过于严格则抑制了代理的工作效率。

Plain 的 Skills 机制为团队提供了封装最佳实践的模板。建议优先实现 /plain-audit(安全扫描与依赖漏洞检查)和 /plain-migrate(数据库迁移与数据一致性验证)两类技能,前者覆盖安全红线,后者覆盖数据完整性底线。这两类技能的经验可迁移性最强,也最能体现双模式框架的协作价值。


资料来源:GitHub 仓库 dropseed/plain(https://github.com/dropseed/plain)