增长案例库 Maxed 归档 AI自动化综合

一句提示、一个按钮,一套完整部署的系统——这就是 2026 年的 AI 工程

One Prompt. One Button. A Fully Deployed System. This Is What AI Engineering Looks Like in 2026

中文译文 · 19k 字

一句话摘要

展示 2026 年 AI 工程的极简交付形态

一句提示词。一个按钮。一套完全部署的系统。这就是 2026 年的 AI 工程 2026 年 7 月 15 日 · 13 分钟阅读 · 查看原文 ↗ Claude Obsidian AI MCP 六个月前,这需要一名后端开发者、一名 DevOps 工程师和两周时间。今天,只需要一句话和 Claude。下面是完整架构——以及为什么大多数开发者还没想明白它。 大多数人对 AI 的心智模型是错的。 他们以为:AI 助手 → 你提问 → 它回答。 2026 年的现实是:AI 智能体 → 你描述一个系统 → 它构建、部署,并把那个系统连接到你的环境。不是原型。不是代码片段。而是一个正在运行的应用。 这种转变有一个名字:Generative App Architecture(生成式应用架构)。而让它变得实用的技术栈——Claude + Obsidian + MCP——现在任何人都可以使用。 Generative App Architecture 到底是什么意思 传统软件开发: Generative App Architecture: AI 智能体不只是写代码。它在底层运行一个完整的 Agentic Loop: 第 1 步——拆解 你的抽象请求("为一家洗车店构建 CRM")被拆成几十个原子子任务:数据库 schema、UI 组件、通知逻辑、认证流程、API 端点。 第 2 步——通过 MCP 映射环境 通过 Model Context Protocol,智能体立刻理解自己能访问哪些工具——你的文件系统、已安装的软件包、正在运行的服务、可用的 API。 第 3 步——迭代构建和测试 智能体写代码、执行代码、捕获编译错误、修复并重新测试——全程自主——直到系统正确运行。 第 4 步——上下文部署 输出不是一个装着代码的文本文件。它是一个真实运行的本地环境,或一个可部署的 Web 应用。 这就是"辅助开发者的工具"和"彻底替代构建流水线的系统"之间的区别。 以 Claude 为引擎——三种部署模式 模式 1——Claude Artifacts 这是从提示词到运行中应用最快的路径。当你让 Claude 构建某样东西时,它会打开一个交互式 Artifact 窗口,在你眼前实时组装、编译并运行一个完整的 Web 应用——React、HTML、JavaScript。 你可以直接在 Artifact 内与运行中的应用交互,用自然语言继续迭代,并导出完整压缩包。 一条能生成生产就绪财务追踪器的提示词: Claude Artifacts 返回的东西——一个完整 React 应用: 这就是完整应用。一句提示词。立即在 Claude Artifacts 内运行。 模式 2——Claude + MCP(本地部署) MCP(Model Context Protocol)让 Claude 直接访问你的本地环境。一句提示词不只是生成代码——它会在硬盘上创建文件夹、通过终端安装软件包、写配置文件,并启动本地服务器。 把 Claude 连接到你文件系统的 MCP 配置: 启用这份配置之后,只需一句提示词: Claude 会通过 MCP 端到端执行它——创建目录结构、安装 Node 软件包、编写数据库 schema、构建 UI、启动服务器。你会拿到一个 localhost URL。 模式 3——带公司标准的 Claude Projects 只需把你的 UI kit、design tokens、API 文档和安全要求上传到一个 Claude Project 一次。此后 Claude 生成的每个系统都会自动遵循你的内部技术栈。 以 Obsidian 为 AI 指挥中心 2026 年的 Obsidian 不是一款笔记应用。它是一个个人 AI 指挥中心,你积累的知识库会成为你构建的每个系统的上下文层。 架构上的转变:你的 vault 不再是存储。它是 RAG(Retrieval Augmented Generation,检索增强生成)——一个 AI 智能体在执行任何任务之前都会查询的活知识库。 让它运转起来的插件栈: Smart Connections——索引你的整个 vault,并在每次 AI 调用时把相关笔记作为上下文发送。 Obsidian Copilot——把你的 vault 直接连接到 Claude API。只需配置一次: 以 Canvas 作为系统设计界面 一句提示词创建一个交互式 Obsidian Canvas,Claude 会把完整系统架构铺成相连的区块。 Claude 以结构化文件形式生成的 Canvas 输出: 用于完全隐私的本地 LLM 对于敏感数据——客户系统、财务工具、内部工具——你让请求经过本地模型,而不是云端 API。零数据离开你的机器。 配置 Obsidian Copilot 使用本地端点: 本地模型 + MCP bridge: 把一个 .md 文件放进你的 Obsidian AI-Inbox,其中写入构建提示词。bridge 会捡起它,通过本地模型路由,在线下 Projects 文件夹中构建系统,并把完成说明写回 Obsidian。 完整工作流——从想法到已部署系统 从第 1 步到应用运行的总时间:4-12 分钟。 这次转变代表什么 这并不是一种更快写代码的方法。 这是想法与执行之间一种不同的关系。 过去,能构建什么受技术能力和时间限制。非开发者造不了 CRM。独立开发者无法同时构建五套系统。团队无法用几小时而不是几周交付。 这三个约束全都消失了。 新的约束是思考的清晰度——能否准确描述你需要什么、理解什么算好输出,并对其进行迭代。这是一项思维技能,而不是技术技能。 Generative App Architecture 不会让开发者过时。它会让"以系统方式思考——在构建之前推理自己需要什么"的能力,变得比编写实现代码的能力有价值得多。 技术栈已经在这里。模型能力已经足够。唯一剩下的变量,是你正在用它构建,还是只在读别人如何构建。 本文描述截至 2026 年 7 月 Claude、Obsidian 和 MCP 已提供的能力。具体插件版本和 API 配置可能变化。实施前请务必核对最新文档。 感谢阅读。 提示词 { "provider": "ollama", "model": "qwen2.5-coder:32b", "baseUrl": "http://localhost:11434", "systemPrompt": "You are a local system builder with access to the user's filesystem via MCP. Build complete working systems. Never send data to external APIs without explicit instruction." } { "provider": "anthropic", "model": "claude-opus-4-8", "apiKey": "YOUR_ANTHROPIC_KEY", "systemPrompt": "You are a system architect. You have access to the user's complete knowledge vault as context. When building systems, reference their existing notes, past decisions, and established patterns. Output: working code + Obsidian file structure.", "contextWindow": { "includeActiveFile": true, "includeLinkedFiles": true, "includeRecentFiles": 10, "includeFolders": ["Projects", "Systems", "Decisions"] } } import { useState, useEffect } from "react"; const CATEGORIES = ["Housing","Food","Transport","Entertainment","Health","Savings","Income","Crypto","Other"]; const CRYPTO_IDS = { BTC: "bitcoin", ETH: "ethereum", SOL: "solana" }; export default function FinanceTracker() { const [transactions, setTransactions] = useState(() => JSON.parse(localStorage.getItem("transactions") || "[]") ); const [cryptoPrices, setCryptoPrices] = useState({}); const [form, setForm] = useState({ description:"", amount:"", category:"Other", type:"expense", date:"" }); const [darkMode, setDarkMode] = useState(false); useEffect(() => { const ids = Object.values(CRYPTO_IDS).join(","); fetch(`https://api.coingecko.com/api/v3/simple/price?ids=${ids}&vs_currencies=usd`) .then(r => r.json()) .then(data => { const prices = {}; Object.entries(CRYPTO_IDS).forEach(([sym, id]) => { prices[sym] = data[id]?.usd || 0; }); setCryptoPrices(prices); }); }, []); useEffect(() => { localStorage.setItem("transactions", JSON.stringify(transactions)); }, [transactions]); const addTransaction = () => { if (!form.description || !form.amount) return; setTransactions(prev => [...prev, { ...form, id: Date.now(), amount: parseFloat(form.amount), date: form.date || new Date().toISOString().split("T")[0] }]); setForm({ description:"", amount:"", category:"Other", type:"expense", date:"" }); }; const totalIncome = transactions.filter(t => t.type === "income").reduce((s,t) => s + t.amount, 0); const totalExpenses = transactions.filter(t => t.type === "expense").reduce((s,t) => s + t.amount, 0); const netWorth = totalIncome - totalExpenses; const bg = darkMode ? "#0D0D0D" : "#F9F7F4"; const card = darkMode ? "#1A1A1A" : "#FFF"; const text = darkMode ? "#F0F0F0" : "#1A1A1A"; const border = darkMode ? "#2A2A2A" : "#E8E8E8"; return ( <div style={{ minHeight:"100vh", background:bg, color:text, fontFamily:"system-ui, sans-serif" }}> <div style={{ maxWidth:800, margin:"0 auto", padding:"24px 16px" }}> <div style={{ display:"flex", justifyContent:"space-between", marginBottom:24 }}> <div> <h1 style={{ fontSize:22, fontWeight:500, margin:0 }}>Finance Tracker</h1> <p style={{ margin:"4px 0 0", fontSize:13, color: netWorth >= 0 ? "#22C55E" : "#EF4444" }}> Net worth: ${netWorth.toFixed(2)} </p> </div> <button onClick={() => setDarkMode(!darkMode)} style={{ padding:"8px 14px", borderRadius:8, border:`1px solid ${border}`, background:card, color:text, cursor:"pointer" }}> {darkMode ? "Light" : "Dark"} </button> </div> <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr", gap:10, marginBottom:20 }}> {[["Income","#22C55E",totalIncome],["Expenses","#EF4444",totalExpenses]].map(([label,color,val]) => ( <div key={label} style={{ background:card, border:`1px solid ${border}`, borderRadius:10, padding:14 }}> <p style={{ margin:0, fontSize:12, color:"#999" }}>{label}</p> <p style={{ margin:"4px 0 0", fontSize:20, fontWeight:600, color }}>${val.toFixed(2)}</p> </div> ))} </div> <div style={{ background:card, border:`1px solid ${border}`, borderRadius:10, padding:16, marginBottom:20 }}> <div style={{ display:"grid", gridTemplateColumns:"2fr 1fr 1fr", gap:8, marginBottom:8 }}> <input placeholder="Description" value={form.description} onChange={e => setForm(p => ({ ...p, description: e.target.value }))} style={{ padding:"9px 12px", borderRadius:8, border:`1px solid ${border}`, background:bg, color:text, fontSize:13 }} /> <input type="number" placeholder="Amount" value={form.amount} onChange={e => setForm(p => ({ ...p, amount: e.target.value }))} style={{ padding:"9px 12px", borderRadius:8, border:`1px solid ${border}`, background:bg, color:text, fontSize:13 }} /> <select value={form.type} onChange={e => setForm(p => ({ ...p, type: e.target.value }))} style={{ padding:"9px 12px", borderRadius:8, border:`1px solid ${border}`, background:bg, color:text, fontSize:13 }}> <option value="expense">Expense</option> <option value="income">Income</option> </select> </div> <div style={{ display:"grid", gridTemplateColumns:"2fr auto", gap:8 }}> <select value={form.category} onChange={e => setForm(p => ({ ...p, category: e.target.value }))} style={{ padding:"9px 12px", borderRadius:8, border:`1px solid ${border}`, background:bg, color:text, fontSize:13 }}> {CATEGORIES.map(c => <option key={c}>{c}</option>)} </select> <button onClick={addTransaction} style={{ padding:"9px 20px", borderRadius:8, background:"#E8692A", color:"#fff", border:"none", cursor:"pointer", fontSize:13, fontWeight:500 }}> Add </button> </div> </div> <div style={{ background:card, border:`1px solid ${border}`, borderRadius:10, overflow:"hidden" }}> <p style={{ margin:0, padding:"12px 16px", borderBottom:`1px solid ${border}`, fontSize:13, fontWeight:500 }}> Transactions ({transactions.length}) </p> {transactions.slice().reverse().map(t => ( <div key={t.id} style={{ display:"flex", justifyContent:"space-between", alignItems:"center", padding:"11px 16px", borderBottom:`1px solid ${border}` }}> <div> <p style={{ margin:0, fontSize:13, fontWeight:500 }}>{t.description}</p> <p style={{ margin:"2px 0 0", fontSize:12, color:"#999" }}>{t.category} · {t.date}</p> </div> <span style={{ fontSize:14, fontWeight:600, color: t.type==="income" ? "#22C55E" : "#EF4444" }}> {t.type==="income" ? "+" : "-"}${t.amount.toFixed(2)} </span> </div> ))} </div> </div> </div> ); } # 安装 Ollama curl -fsSL https://ollama.com/install.sh | sh # 拉取一个具备编码能力的模型 ollama pull llama3.2:latest # 或者使用更强的代码生成模型: ollama pull qwen2.5-coder:32b # 启动本地服务器 ollama serve # 运行于 localhost:11434 Obsidian Canvas 中的提示词: "为我的 Twitter 账号设计一条内容生产流水线。 我每周发布 3 篇文章,管理 5 笔赞助合作。 参考我现有的内容日历笔记。" 输出:带有相连区块的 Canvas: → 内容创意(从你的兴趣笔记中提取) → 初稿 → 审核 → 发布工作流 → 带截止日期提醒的赞助追踪 → 分析仪表盘 → 自动交叉发布逻辑 → 每个区块都链接到对应的 Obsidian 文件 import requests import json from pathlib import Path from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler OBSIDIAN_INBOX = Path.home() / "Obsidian" / "AI-Inbox" PROJECTS_DIR = Path.home() / "Projects" OLLAMA_URL = "http://localhost:11434/api/generate" class InboxWatcher(FileSystemEventHandler): """ 监视 Obsidian AI-Inbox 文件夹。 当新的 .md 文件出现时,把它视为构建提示词。 传给本地 LLM -> 通过 MCP 执行 -> 报告结果。 """ def on_created(self, event): if not event.src_path.endswith(".md"): return prompt_file = Path(event.src_path) prompt = prompt_file.read_text() print(f"[Inbox] New prompt: {prompt_file.name}") self.execute_prompt(prompt, prompt_file.stem) def execute_prompt(self, prompt: str, project_name: str): response = requests.post(OLLAMA_URL, json={ "model": "qwen2.5-coder:32b", "prompt": f"""You are a system builder. Build this system: {prompt} Output a JSON plan with: {{ "project_dir": "relative path", "files": [ {{"path": "relative path", "content": "file content"}} ], "commands": ["npm install", "etc"], "summary": "what was built" }}""", "stream": False }) plan = json.loads(response.json()["response"]) project_dir = PROJECTS_DIR / plan["project_dir"] project_dir.mkdir(parents=True, exist_ok=True) for file_spec in plan["files"]: file_path = project_dir / file_spec["path"] file_path.parent.mkdir(parents=True, exist_ok=True) file_path.write_text(file_spec["content"]) print(f"[Build] Created: {file_path}") result_file = OBSIDIAN_INBOX / f"{project_name}-result.md" result_file.write_text( f"# Build Complete: {project_name}\n\n" f"**Location:** {project_dir}\n\n" f"**Summary:** {plan['summary']}\n\n" f"**Files created:** {len(plan['files'])}\n" ) print(f"[Done] Result written to Obsidian") if __name__ == "__main__": OBSIDIAN_INBOX.mkdir(exist_ok=True) observer = Observer() observer.schedule(InboxWatcher(), str(OBSIDIAN_INBOX), recursive=False) observer.start() print(f"[Watching] {OBSIDIAN_INBOX}") try: while True: import time; time.sleep(1) except KeyboardInterrupt: observer.stop() observer.join() { "mcpServers": { "filesystem": { "command": "npx", "args": [ "-y", "@modelcontextprotocol/server-filesystem", "/Users/yourname/Projects" ] }, "terminal": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-terminal"] }, "sqlite": { "command": "npx", "args": [ "-y", "@modelcontextprotocol/server-sqlite", "--db-path", "/Users/yourname/Projects/app.db" ] } } } { "nodes": [ { "id": "ideation", "type": "file", "file": "Systems/ContentPipeline/Ideation.md", "x": 0, "y": 0, "width": 300, "height": 200, "color": "1" }, { "id": "draft", "type": "file", "file": "Systems/ContentPipeline/Draft.md", "x": 400, "y": 0, "width": 300, "height": 200, "color": "3" }, { "id": "sponsors", "type": "file", "file": "Systems/ContentPipeline/SponsorTracker.md", "x": 0, "y": 300, "width": 300, "height": 200, "color": "5" }, { "id": "analytics", "type": "file", "file": "Systems/ContentPipeline/Analytics.md", "x": 400, "y": 300, "width": 300, "height": 200, "color": "6" } ], "edges": [ { "id": "e1", "fromNode": "ideation", "fromSide": "right", "toNode": "draft", "toSide": "left", "label": "approved concepts" }, { "id": "e2", "fromNode": "sponsors", "fromSide": "right", "toNode": "draft", "toSide": "bottom", "label": "brief integration" } ] } 为一家洗车企业构建并部署一套本地 CRM 系统。 在 ~/Projects/carwash-crm/ 创建项目。 自动安装依赖。 设置 SQLite 数据库,包含以下表: - customers(name、phone、email、vehicle、notes) - visits(customer_id、date、service、price、status) - staff(name、role、schedule) 构建一个 Web 界面,包含: - 客户搜索和客户资料 - 每位客户的到访历史 - 按月收入仪表盘 - 短信提醒系统(Twilio 集成,仅配置) 完成后启动开发服务器。 就绪后报告 localhost URL。 想法 → 规格 → 设计 → 前端开发 → 后端开发 → 数据库搭建 → API 集成 → 测试 → 部署 耗时:数周。成本:数千美元。 第 1 步——输入 在 Obsidian 的 AI 面板中写下: "带加密货币集成和月度预算追踪的 个人财务系统。" 按下 Generate。 第 2 步——上下文组装 Smart Connections 插件扫描你的 vault。 找到你过去 3 个月的财务笔记。 把它们作为上下文发送到 Claude API。 第 3 步——架构 Claude(Opus 4.8)设计系统: - 数据库 schema - UI 组件 - API 集成 - 文件结构 第 4 步——构建 Claude(Sonnet 5)通过 MCP 实现: - 创建 ~/Projects/finance-tracker/ - 安装依赖 - 写入所有文件 - 在 localhost:3000 启动开发服务器 第 5 步——结果 Obsidian 创建文件夹:Finance System/ 内部包含:互相链接的仪表盘、配置笔记, 以及运行中应用的直接链接。 想法 → 提示词 → 运行中的系统 耗时:几分钟。成本:API tokens。 [Claude Project 上下文包含:] - design-system.md(颜色、排版、间距) - api-standards.md(认证模式、错误码) - security-policy.md(输入验证规则、CORS 配置) - stack.md(React 18、TypeScript、Tailwind、Prisma、PostgreSQL) 提示词: "构建一个带邮箱验证的客户入驻表单, 提交后自动写入 Notion 数据库。" 输出:完全匹配你的技术栈的生产就绪代码 ——不需要清理。 构建一个个人财务追踪应用,包含: 功能: - 交易日志(按分类添加/编辑/删除) - 带进度条的月度预算视图 - 从 CoinGecko API 拉取实时价格的加密资产组合追踪器 - 实时更新的净资产计算 - 深色模式开关 技术要求: - 单文件 React 应用 - 只使用 useState + useEffect(不使用外部状态管理) - 使用 Tailwind CSS 做样式 - 从公开 API 拉取数据(无需认证) - 移动端响应式 数据: - 跨会话持久化到 localStorage - 把交易导出为 CSV 输出:可直接部署的完整自包含应用。 标签:# X # Claude # Obsidian # AI # MCP # Crypto # Design # Sonnet # Rag 相关文章 Every Morning I Re-Taught Claude My Whole Life. It Forgot by Lunch. One File Ended the Loop 人们花了多年寻找完美的提示词。答案从来不在于你怎么问,而在于你开口之前,AI 已经对你知道些什么。Claude AI Obsidian MCP

原文参考:https://maxed.wiki/posts/one-prompt-one-button-a-fully-deployed-system-this-is-what-ai-engineering-looks-like-in-2026/ (Maxed.wiki,本页为站内中文整理)