开发者
I got tired of watching 40 Kalshi tabs, so I built a self-hosted signal monitor
I kept hearing about Kalshi. The commercials, the mentions, and then one morning CNN was talking about Kalshi prediction odds like they were a weather report. So I went and looked. And I had no idea what I was seeing. Kalshi is really hard to understand when you're new to it. You get markets, contracts, prices that are also probabilities, volume, movement, and none of it tells you what's actually worth paying attention to. I wanted something that would translate what I was looking at into something I could understand and, ideally, act on. That was the whole original goal: make the firehose legible. Then, of course, I kept adding to it, because once you can read the flow you start wanting an edge in it. Who doesn't. So Trade Hunter grew from a translation layer into a translation layer with detection on top. This is a writeup of what it became, why I made the design choices I made, and the parts I'm still not sure about. I'd rather you poke holes in it now than find the breakpoints the hard way. If you think a decision here is wrong, please let me know. The comments are the point of this post, not an afterthought. Where this came from Basically, I couldn't read Kalshi, and I wanted to. Trade Hunter is the original tool I built to fix that for myself, and it's the one I still run when I want a live view. So this isn't a polished sequel to anything. It's the thing I built because I wanted it to exist, flaws and design bets included, and I'd rather show you those directly. The core idea never changed even as I piled features on: watch live Kalshi WebSocket feeds and surface an unusual move while it's still moving, rather than reading about it after the fact, or on CNN the next morning. What it actually does Trade Hunter subscribes to live Kalshi feeds across every market you track. Multi-contract series like the Fed rate decisions or who will win Top Chef fan out automatically to all open contracts, so you point it at one thing and it watches the whole family. When some
AI 资讯
How I Cut Our AI API Bill by 95% — The Engineering Playbook
How I Cut Our AI API Bill by 95% — The Engineering Playbook When our finance lead forwarded me the AWS bill for March, I almost choked on my coffee. We were a team of nine engineers shipping AI features, and somehow we'd burned through enough on inference to cover two salaries. The worst part? I hadn't even noticed because the charges were scattered across OpenAI, Anthropic, and a couple of side experiments. That's the moment I decided to actually treat LLM spending like a real infrastructure problem instead of a credit card swipe. What follows is the playbook I wish I'd had on day one. These aren't theoretical tips — they're the exact moves I made across three products to get our run-rate down to roughly 5% of where it started, without shipping worse software. The Harsh Truth About Model Defaults Here's the dirty secret nobody tells you in the LLM hype cycle: most teams default to the most famous model for every single call. GPT-4o for everything. Claude Sonnet for everything. Then they wonder why their "simple AI feature" costs them a kidney. The model selection decision is where I recovered the majority of my budget. When you look at it rationally, the gap between the flagship tier and the cheap-tier models is absurd for tasks that don't require frontier reasoning. This is the matrix I landed on, and it still governs our routing today: Task What I Used To Use What I Use Now Cost Cut Simple chat GPT-4o ($10/M out) DeepSeek V4 Flash ($0.25/M) 97.5% Classification GPT-4o-mini ($0.60/M) Qwen3-8B ($0.01/M) 98.3% Code generation GPT-4o ($10/M) DeepSeek Coder ($0.25/M) 97.5% Summarization GPT-4o ($10/M) Qwen3-32B ($0.28/M) 97.2% Translation GPT-4o ($10/M) Qwen-MT-Turbo ($0.30/M) 97% I want you to really sit with the classification row. Qwen3-8B at $0.01 per million output tokens. That's sixty times cheaper than GPT-4o-mini. For a binary sentiment classifier, the accuracy difference in my benchmarks was under 1.5 percentage points. The ROI math isn't even close. The code
开源项目
🔥 google-antigravity / antigravity-sdk-python - A Python library for building AI agents that leverage the fu
GitHub热门项目 | A Python library for building AI agents that leverage the full power of Google Antigravity. | Stars: 2,250 | 21 stars today | 语言: Python
AI 资讯
Build a UGC video moderation pipeline with FFmpeg + NudeNet
TL;DR If your product lets strangers upload video, you need moderation before launch, not after the first bad upload. We will build a small-team pipeline: extract frames with FFmpeg, score them with NudeNet (ONNX Runtime, CPU-friendly), route uploads into approve / human-review / block by confidence, and log every decision. No trust-and-safety department required. 📦 Code: github.com/USER/ugc-moderation, replace before publishing ⚠️ Note: this is a sensitive area. The goal here is the engineering shape (sampling, scoring, routing, auditing), not detection of any specific content. Keep test fixtures clean and lawful. A model does not decide what is allowed. It produces a score. You decide where the lines go. The whole design is about routing scores sensibly and sending the uncertain middle to a human. The architecture 🧠 upload ──> extract sample frames (ffmpeg) ──> score frames (NudeNet / ONNX) ──> aggregate to one confidence ──> route: high-confidence clean -> auto-approve uncertain middle band -> human review queue high-confidence violation -> auto-block ──> write an audit record for every decision The economics only work if the middle band is small. A decent model makes most uploads obviously fine or obviously not, so a human only ever sees the genuinely ambiguous slice. 1. Sample frames, do not score every frame You cannot afford every frame and you do not need it. Pull one frame per second (or scene-change keyframes) with FFmpeg. # extract 1 frame per second into ./frames mkdir -p frames ffmpeg -i upload.mp4 -vf "fps=1" -q :v 3 frames/frame_%05d.jpg Prefer scene changes to catch more variety with fewer frames: # keyframes where the scene actually changes ffmpeg -i upload.mp4 -vf "select='gt(scene,0.3)',showinfo" -vsync vfr frames/scene_%05d.jpg 💡 Tip: a 30-minute upload at 1 fps is ~1,800 frames. Scene-change sampling often cuts that by an order of magnitude with little loss for moderation purposes. 2. Score frames with NudeNet NudeNet runs on ONNX Runtime on pla
AI 资讯
My AI agent tried to ship a mistake we'd already reverted
A month ago we added a card_token column to the users table so a background job could retry failed Pro charges. It lasted about two days. Storing card data in your own database drops you into PCI-DSS (the compliance standard that kicks in the moment card data touches your systems), so we pulled it and moved to Stripe-managed payment methods. Last week the charges started failing again. New Claude Code session, no memory of any of that. Its plan? Add a card_token column to users and retry. I don't really blame the agent. It had the context the first time and it was right. The problem is that context died when the session closed. That's the part I never see mentioned about building with agents: the code sticks around, the reasoning doesn't. People leave a trail without trying. A commit message, a PR comment, the Slack thread before it. Agents don't, and the prompt that explained everything is gone by morning. So I built Selvedge to hold onto the reasoning. What happened the second time Selvedge is a local MCP server the agent calls as it works. There's a four-line block in our CLAUDE.md that says, roughly: before you touch an entity, check if we've been here before. $ selvedge prior-attempts users.card_token users.card_token Prior attempt 28 days ago ( reverted after 2 days ) Reasoning Added to store card tokens for one-click retries. Outcome REVERTED — kept card data out of our own DB to stay clear of PCI-DSS scope ; moved to Stripe-managed methods. So it didn't add the column. It charged off_session against the saved Stripe PaymentMethod instead. Charge retried, no card data in our database, done. We paid for that lesson once. How it works The agent writes down why live, in the moment, from the same context that made the change. That's the whole trick. A lot of the "git blame for AI" tools take your diff afterward and ask a second model to explain it. That's a guess. It reads well, but you can't really build on it. Selvedge stores what the agent actually meant, in i
AI 资讯
I Got Tired of My Portfolio Looking Like a List of Links. So I Built an MCP Server for It.
The obvious fix for "my projects all look similar" is a better README — more screenshots, clearer descriptions, maybe a comparison table. I considered that for about five minutes and decided it was still just a nicer list of links. What actually made a portfolio project feel different was making it something you could talk to instead of read. That's what MCP (Model Context Protocol) is built for — it's the standard that lets AI clients like Claude Desktop call external tools directly, not just process text. So I built a server that exposes my 9 projects as queryable tools instead of static entries. What is MCP, and why does it matter here Almost every AI-developer portfolio I've seen is a list of links. Mine now includes something you can actually talk to . Open Claude Desktop, connect my server, and ask "what has Ayush built with FastAPI?" — it doesn't guess from a cached README, it calls a real tool and answers from structured, live data. What I built A Python MCP server ( FastMCP , stdio transport) exposing five tools: list_projects — short summary of all 9 projects get_project_details(project_name) — full stack, GitHub link, demo URL for one project, fuzzy-matched by name search_projects_by_stack(technology) — "show me everything using Groq" or "LangGraph" or "React" get_flagship_project — the single best project to look at first get_resume_summary — background, target role, core stack The data itself lives in plain Python dictionaries right now — no database needed for something this size. Each tool is a thin function around that data, decorated with @mcp.tool() . @mcp.tool () def search_projects_by_stack ( technology : str ) -> list [ dict ]: """ Find all projects that use a given technology or tool. """ query = technology . lower (). strip () matches = [ { " name " : p [ " name " ], " stack " : p [ " stack " ], " github " : p [ " github " ]} for p in PROJECTS if any ( query in tech . lower () for tech in p [ " stack " ]) ] return matches or [{ " message " : f
AI 资讯
FROST 的治理哲学:为什么每个 Agent 系统都需要一部宪法
FROST 的治理哲学:为什么每个 Agent 系统都需要一部宪法 "细胞会死,但谱系会存续。Agent 会消亡,但宪法会传承。资产会永存。" 在 AI Agent 框架百花齐放的 2026 年,我们见证了一个有趣的现象:框架越来越多,治理却越来越缺失。LangChain 给了你工具链,CrewAI 给了你角色扮演,AutoGen 给了你对话——但没有人回答一个关键问题: 当你的 Agent 家族有十代、百代,谁来保证它们的行为不越界? 这就是 FROST 要解决的问题。 一、一个被忽视的问题:Agent 治理真空 想象这样一个场景:你构建了一个 Agent 系统,它帮你处理客户咨询、自动写报告、管理财务。一开始只有 3 个 Agent,你都能监控。三个月后,Agent 数量变成了 30 个——有些是你创建的,有些是 Agent 自己创建的。 问题来了: 某个 Agent 开始访问不该访问的数据 某个 Agent 创建的子 Agent 继承了一份不该继承的权限 某个 SOP 工作流在运行中被人悄悄修改了 这不是科幻场景,这是今天 Agent 系统正在发生的事。 根本原因 :现有框架的"治理"要么是提示词级别的软约束("请你不要访问这些数据"),要么是事后的日志审计。没有一个是代码级别、架构级别的硬约束。 FROST 的设计哲学是: 治理必须是架构的一部分,而不是补丁。 二、FROST 的宪法模型:四层治理 FROST 把治理拆解为四个层次,每一层都有对应的代码实现: 第一层:只读继承——权限的代码级强制 在大多数框架中,Agent 之间的数据共享靠的是"约定"。FROST 用的是 HierarchicalStore ——一种层级化记忆容器: class HierarchicalStore : """ 层级化记忆存储。 祖先 Store 对后代只读——后代可以继承,但不能篡改。 """ def __init__ ( self , data = None , parent = None , readonly = False ): self . _data = data or {} self . _parent = parent self . _readonly = readonly # 关键:只读标记 def save ( self , key , value ): if self . _readonly : raise PermissionError ( " 只读 Store 禁止写入 " ) self . _data [ key ] = value def load ( self , key , default = None ): if key in self . _data : return self . _data [ key ] if self . _parent : return self . _parent . load ( key , default ) return default 注意 readonly 参数。当一个 Agent 创建子 Agent 时,子 Agent 对父 Agent 的 Store 是 只读的 。这不是提示词告诉 Agent "请你不要修改",而是代码直接抛出异常。 这意味着 :即使 LLM 产生了幻觉,试图越权写入,代码层面也会拒绝执行。 第二层:SOP 宪法校验——工作流的可审计性 在 FROST 中,SOP 不是随便定义的步骤列表,而是经过祖辈审核的"宪法文本": def validate_sop ( ancestor_sop , descendant_sop ): """ 祖辈验证后代的 SOP 是否合规。 检查点: 1. 后代 SOP 的步骤不能超出祖辈定义的边界 2. 后代 SOP 不能调用未授权的 Skill 3. 后代 SOP 的数据访问不能超出权限范围 """ # 检查 1:步骤边界 for step in descendant_sop . steps : if step not in ancestor_sop . allowed_steps : raise SOPValidationError ( f " 步骤 { step } 超出祖辈定义的边界 " ) # 检查 2:Skill 授权 for skill in descendant_sop . required_skills : if skill not in ancestor_sop . authorized_skills : raise SOPValidationError ( f " Skill { skill } 未获授权 " ) return True 这意味着 :任何后代 Agent 想要执行的工作流,都必
AI 资讯
Modeling the Expected Value of a Sealed Card Box (and Where the Number Quietly Lies)
A friend messaged me a photo of a sealed booster box last month with one question: "worth it?" He'd already decided, really. The chase card in that set was all over his feed, so the box felt like a good deal. I asked him to send me the pull rates instead of the hype, and we spent twenty minutes turning "worth it?" into something we could actually compute. That exercise is a small, self-contained data problem. It's also a good example of how a clean-looking model can hand you a confident number that doesn't survive contact with reality. If you like building little estimators, this one is worth doing carefully, because the interesting part isn't the formula. It's everything the formula assumes. The formula is the easy part Expected value of a box is a weighted sum. Each card you can pull has a probability and a market value, and you multiply the two across every slot the box gives you. That's it. Undergrad probability. Here's a stripped-down version for a hypothetical set. I'm using made-up numbers so nobody mistakes this for real pull data — the point is the shape of the computation, not the specific set. # One "hit slot" in a box: probabilities cover the full outcome space. # Values are illustrative market estimates in USD. hit_table = [ { " name " : " Alt-art chase " , " p " : 0.0125 , " value " : 180.00 }, { " name " : " Secret rare " , " p " : 0.030 , " value " : 45.00 }, { " name " : " Full-art rare " , " p " : 0.100 , " value " : 8.00 }, { " name " : " Standard hit " , " p " : 0.400 , " value " : 0.55 }, { " name " : " No notable hit " , " p " : 0.4575 , " value " : 0.06 }, ] assert abs ( sum ( row [ " p " ] for row in hit_table ) - 1.0 ) < 1e-9 ev_per_slot = sum ( row [ " p " ] * row [ " value " ] for row in hit_table ) hit_slots_per_box = 36 # e.g. one meaningful slot per pack ev_box = ev_per_slot * hit_slots_per_box print ( f " EV per slot: $ { ev_per_slot : . 2 f } " ) # $4.65 print ( f " EV per box: $ { ev_box : . 2 f } " ) # $167.31 The box costs $150 sea
AI 资讯
Before adopting DSPy, prove the LM program has a contract
Before adopting DSPy, prove the LM program has a contract DSPy is easy to undersell. If you describe it as "a nicer way to write prompts", you will probably test the wrong thing. The better first test is this: can your language-model workflow be expressed as a small program with declared inputs, declared outputs, measurable examples, and an optimizer that is allowed to change prompts without changing the business boundary? That is the point where DSPy starts to make sense. The upstream README positions DSPy as a framework for programming, rather than prompting, foundation models. The current Doramagic project pack for stanfordnlp/dspy also points at the same starting command: pip install dspy . The package metadata I checked today declares name="dspy" , version 3.3.0b1 , and Python >=3.10,<3.15 . The GitHub API snapshot showed the repository was still active, with a push on 2026-07-05 and recent pull requests around empty evaluation sets, document formatting, and GEPA trace attribution. That activity is useful, but it is not the adoption proof. The proof is whether your own task can survive three separations. 1. Separate the task contract from the prompt In DSPy terms, the first artifact worth reading is not a clever prompt. It is the Signature. A Signature says what goes in and what must come out. A Module wraps that contract into something callable. An Adapter turns the contract into the provider-facing prompt format and parses the model response back into fields. That gives you a practical review question: Can the team name the output fields before anyone starts tuning wording? If the answer is no, DSPy will not rescue the workflow. You are still negotiating the task itself. The first pass should be a tiny contract: input text, retrieved context if needed, answer, citations, confidence, or whatever fields the product actually needs. Do not start with agents, tools, or multi-stage pipelines. 2. Separate compilation from runtime correctness DSPy optimizers can impr
AI 资讯
Where Do Your LLM API Keys Actually Live?
If someone compromised one of your project's dependencies today, would they be able to steal your...
AI 资讯
Building a 'Chief Health Officer' with LangGraph: Automatically Filter Your Food Delivery Based on Real-Time Blood Sugar
We’ve all been there: it’s 7:00 PM, you’re exhausted after a long sprint, and you open a food delivery app. Your brain screams "Double Cheeseburger," but your body is still recovering from that mid-afternoon sugar spike. What if your phone was smart enough to say, "Hey, your blood sugar is currently 160 mg/dL and rising—maybe skip the extra fries?" In this tutorial, we are building a Chief Health Officer (CHO) Agent . This isn't just a simple chatbot; it’s a sophisticated AI Agent using LangGraph to bridge the gap between real-time medical data (CGM) and real-world actions (Food Delivery APIs). By leveraging automation , function calling , and state machines , we’ll create a system that actively protects your metabolic health. The Architecture: How the CHO Agent Thinks To build a reliable agent, we need a "stateful" workflow. We aren't just sending a prompt to an LLM; we are creating a loop that monitors glucose levels, analyzes food options, and interacts with the browser. graph TD A[Start: Hunger Trigger] --> B{Fetch CGM Data} B -->|Sugar High/Unstable| C[Constraint: Low GI Only] B -->|Sugar Stable| D[Constraint: Balanced Meal] C --> E[Scrape Delivery App Menu] D --> E E --> F[Agent: Analyze Ingredients & GI Index] F --> G[Selenium: Mark/Filter Non-Compliant Items] G --> H[End: Safe Ordering] subgraph "The LangGraph Loop" C D E F end Prerequisites Before we dive into the code, ensure you have the following: LangGraph & LangChain : For the agent's cognitive architecture. Dexcom API Credentials : To fetch real-time Continuous Glucose Monitor (CGM) data. Selenium : For interacting with food delivery web interfaces (Meituan/Ele.me). OpenAI API Key : Specifically for GPT-4o’s reasoning and function-calling capabilities. Step 1: Defining the Agent State In LangGraph, everything revolves around the State . Our CHO agent needs to track the current glucose level, the user's health constraints, and the list of available food items. from typing import TypedDict , List , Anno
AI 资讯
I Built an AI Agent That Remembers Why Customers Leave (And I'm Building My Way Into AI Development)
With over 5 years in customer support and retention, I've lost count of how many times I've seen the same pattern: a customer explains an issue, gets it "resolved," and then has to explain the same problem again weeks later, as if the first conversation never happened. Support systems forget. Customers don't. That frustration, seen over years on the support side, is what led me to this hackathon project. Most support systems and most AI chatbots treat every interaction as isolated. They don't remember. So patterns that should be obvious (repeated complaints, dropping usage, unresolved issues) never get connected until a customer just leaves. That became the seed for my project: the Retention Risk Agent. The Problem With "Forgetful" AI Most AI tools answer questions in the moment, then forget everything. Ask a chatbot about a customer's history, and it only knows what's in that single message, not what happened last week, last month, or across five different support tickets. For churn prediction, that's a fatal flaw. Churn isn't a single event. It's a pattern, a series of small signals that only make sense when viewed together over time. This is something I understand deeply from years of watching it happen firsthand. Cognee is an open-source memory layer for AI agents. Instead of treating each interaction as isolated, it builds a knowledge graph, connecting facts, relationships, and context across everything you feed it. That's exactly what churn detection needed. What I Built I created a Python script that: Ingests customer records (support tickets, usage patterns, plan changes) Uses Cognee to build a memory graph connecting these signals Asks a simple question: "Which customers show signs of churn risk, and why?" The result wasn't a keyword match; it was reasoning. The agent correctly flagged a customer whose usage dropped 80% and who'd ignored two check-in emails. It flagged another who'd complained twice about slow support and mentioned a competitor. And critica
AI 资讯
Guardrails for LLM Apps in Python
Introduction Every post in this series has quietly touched a piece of the same problem. Building Agentic Workflows in Python said a tool's input is untrusted and must be validated before it reaches your code. Building Reliable LLM Applications in Python said the model will confidently invent facts, so ground it and get typed output instead of parsing prose. Neither post named the thing underneath both statements: anything that crosses from outside your code into the model, or from the model back into your code, is untrusted input — a request body from the network, not a trusted internal value. This post names that boundary directly and gathers the defenses in one place — prompt injection (direct and indirect), input validation, output validation, and PII redaction — with the SAFE pattern shown beside every unsafe one it replaces, since this is the security-forward capstone of the series. The Trust Boundary: Three Kinds of Untrusted Input An LLM application has three places where untrusted text enters: User input — anything a person types, uploads, or submits through an API. Retrieved content — Making RAG Accurate in Python built a pipeline that ranks and returns chunks from a document store; those chunks were written by whoever authored the source document, not by you, and a malicious or compromised document can carry text aimed at the model reading it, not at a human reader. Model output — untrusted the moment it's about to be used rather than displayed : passed to a tool, interpolated into a query, or fed into another LLM call as context. A model that just read attacker-controlled retrieved text can be manipulated into producing attacker-controlled output. The single rule under all three: text is data until your code has explicitly decided it's safe to use for anything more than display. Nothing below is executed against a live API — every snippet is illustrative, and none of it uses a real key or a real record. Direct Prompt Injection: Defending the System Prompt
AI 资讯
Prompt Caching and Cost Control in Python
Introduction https://pg-blogs.netlify.app/posts/10-building-reliable-llm-apps-in-python/ closed with a section on picking the right model per task and caching a shared prefix. That was the entry point into a bigger discipline: LLM spend is an engineering variable, not a fixed bill — one you can measure and reduce with the same rigor you'd apply to query latency or memory footprint. This post goes deeper on four levers: how input/output pricing actually works and why the prefix is usually where the money goes, the exact cache_control shape and how to prove a cache hit instead of assuming one, the Batches API for work that isn't latency-sensitive, and model routing — a cheap model triaging requests and escalating only the hard ones. The throughline is honest: measure before you optimize. Every lever here has its own cost; misapplied, it makes things slower or pricier, not cheaper. Token Economics: Why the Prefix Is the Bill LLM providers price input and output tokens separately, and output always costs more — generation is autoregressive (each token depends on every one before it), while input can be processed in parallel. Representative pricing from the current model catalog: Model Input Output Claude Opus 4.8 $5.00 / MTok $25.00 / MTok Claude Sonnet 5 $3.00 / MTok $15.00 / MTok Claude Haiku 4.5 $1.00 / MTok $5.00 / MTok Two things follow: A long system prompt, tool list, or RAG context is billed as input on every request , not written once. Send a 20K-token system prompt on 10,000 requests and that's 200M input tokens — at Opus 4.8 rates, $1,000 before the model has generated a single output token. The shared prefix , not the user's actual question, is usually the dominant cost. Verbose output costs twice — once directly (more output tokens billed at the higher rate), and again because the next turn's history carries that verbosity forward as input. Asking for concise output and setting a sane max_tokens is a cost control, not just a style choice. This is why the tw
AI 资讯
Evaluating LLM Apps in Python
Introduction Building Reliable LLM Applications in Python put it plainly: treat model output as a hypothesis to verify, not a fact to trust. Testing Best Practices in Python put the same discipline in pytest terms: a suite only earns trust by asserting the right things at the right level, unhappy paths included. This post is where those two ideas meet — a pytest assertion either passes or fails against a fixed expected value; an LLM's output is a paragraph of prose that might be right in spirit while differing token-for-token from anything you wrote down in advance. Evaluating it takes a harness, not an assert . That harness has three parts: a golden dataset of representative cases with known-good expected behavior, scoring that turns each case into a pass/fail or a number, and regression testing that runs the harness on every change and fails the build when the score drops. Making RAG Accurate in Python already gave you half of this story — recall@k, precision@k, MRR, nDCG measure whether retrieval found the right chunks. This post measures the other half: whether the generated answer built from those chunks is actually good, which is a genuinely different question a retrieval metric can't answer on its own. Everything below is illustrative, non-executed Python, grounded in the same Anthropic SDK shapes as posts 10/11. The Golden Dataset: Curating Cases, Not Just Inputs A golden dataset is a small, hand-curated set of (input, expected behavior) pairs that represents the ways your application is actually used — not a random sample, and not just the cases that already work. Each case needs enough structure to be scored automatically later: from dataclasses import dataclass , field @dataclass class EvalCase : id : str category : str # "extraction", "qa", "summarization", ... input : str # the prompt/question sent to the system under test expected_exact : str | None = None # non-None only for cases scorable by exact match must_contain : list [ str ] = field ( default_f
AI 资讯
The Model Context Protocol in Python
Introduction Every agent needs tools, and every tool needs a way to reach the model. Building Agentic Workflows in Python built that connection by hand — a hand-written JSON schema, a loop that dispatches on block.name . LLM Frameworks vs. the Raw SDK in Python showed LangChain's @tool turning a plain function into that same schema via bind_tools . Both are still bespoke : the tool lives inside one process, wired to one agent, in one language. The Model Context Protocol (MCP) solves a different problem: it standardizes the wire format between an AI application and a tool server, so the server doesn't have to be rewritten per agent, per framework, or per language. This post covers what that buys you, builds a minimal MCP server and a client that consumes it — both on the official Python SDK — and gives an honest answer to when reaching for a protocol is worth it over a direct tool call. The Problem MCP Solves Without a shared protocol, every pairing of agent framework and tool needs its own glue code: a LangChain @tool wrapper, a hand-rolled schema for the raw SDK, a different wrapper again for whatever framework a teammate picks next — an integration per framework, per tool. That's an M×N problem. MCP flattens it to M+N. A server exposes tools, resources, and prompts once, over a standard JSON-RPC protocol. Any host application — Claude Code, Claude Desktop, VS Code, or your own agent — creates an MCP client that speaks that same protocol, regardless of which framework built the host. Write the server once; every MCP-aware host can use it without new integration code. The protocol itself is intentionally boring: JSON-RPC 2.0 messages for lifecycle negotiation, tool discovery, and tool execution. Discovery ( tools/list ) and execution ( tools/call ) are the two calls that matter for this post: // tools/list response (abbreviated) { "jsonrpc" : "2.0" , "id" : 2 , "result" : { "tools" : [ { "name" : "get_account_balance" , "description" : "Look up the balance for an ac
AI 资讯
The LLM Cost Death Spiral (And How I Got Out of It)
There's a pattern playing out across indie hacker forums, engineering blogs, and Discord servers right now: a founder builds a product on GPT-4-class models, ships it, gets traction — and then opens a bill that makes them question the whole business model. LLM costs have a nasty habit of scaling linearly (or worse) with usage, right at the moment a product starts succeeding. In response, a growing body of developer tutorials is focused on one goal: keeping the intelligence, dropping the invoice. Think of it like the early days of cloud hosting. Companies over-provisioned expensive dedicated servers until autoscaling and cheaper commodity infrastructure made "pay for what you use, and use less of the expensive stuff" the default architecture. The LLM ecosystem is going through its own version of that shift right now, and DeepSeek has become the poster child for the "just as capable, dramatically cheaper" alternative to OpenAI's premium models. Migrating With Minimal Friction The first core question developers are wrestling with is deceptively simple: how do you swap out a model provider without rewriting your whole application? The answer that keeps surfacing is API compatibility layers . Many cost-effective providers, including DeepSeek, expose an API that mirrors OpenAI's own request/response format almost exactly. That means in a lot of codebases, migration isn't a rewrite — it's a find-and-replace of a base URL and an API key. # Before: pointed at OpenAI client = OpenAI ( api_key = " sk-openai-... " , ) # After: same SDK, same code, different provider client = OpenAI ( api_key = " sk-deepseek-... " , base_url = " https://api.deepseek.com/v1 " ) That's it, in the simplest case. Because the OpenAI Python SDK just talks HTTP under the hood, any provider that speaks the same "dialect" can slot in without touching your prompt logic, your function-calling schemas, or your downstream parsing code. The real friction shows up in the details: subtle differences in how mode
开源项目
🔥 bradautomates / claude-video - Give Claude the ability to watch any video. /watch downloads
GitHub热门项目 | Give Claude the ability to watch any video. /watch downloads, extracts frames, transcribes, hands it all to Claude. | Stars: 3,377 | 356 stars today | 语言: Python
开源项目
🔥 OthmanAdi / planning-with-files - Persistent file-based planning for AI coding agents and long
GitHub热门项目 | Persistent file-based planning for AI coding agents and long-running agentic tasks. Crash-proof markdown plans that survive context loss and /clear, plus a deterministic completion gate and multi-agent shared state on disk. Manus-style. Works with Claude Code, Codex CLI, Cursor, Kiro, OpenCode and 60+ agents via the SKILL.md standard. | Stars: 24,557 | 61 stars today | 语言: Python
AI 资讯
🤖 I Built 100 Claude Code Subagents. These Are The 12 That Actually Earn Their Context.
Everyone's building armies of AI "specialists" inside Claude Code. Most of them never trigger, collide with each other, and quietly bloat the very context window they were supposed to protect. I built and stress-tested 100 subagents — official built-ins, the big community collections, and a pile of my own — to find the handful that genuinely earn their keep. Here are the 12 I actually delegate to, the ones I deleted, and the uncomfortable truth about what a subagent is really for. Why I Went Down This Rabbit Hole This is the third time I've done this to myself. First it was 100 Claude Skills . Then 100 MCP servers . Now: subagents. Together they're the three pillars of the Claude Code stack — Skills give an agent competence , MCP servers give it capability , and subagents give it delegation . I'd covered two. The trilogy demanded the third. And subagents are where the hype is loudest right now. Open GitHub and you'll find collections with hundreds of them: VoltAgent's awesome-claude-code-subagents ships 154+ agents across 10 categories with 22.9k stars ; wshobson's marketplace packs 194 agents, 158 skills, and 16 orchestrators into 37.5k stars . The pitch is intoxicating: assemble a team of AI specialists — a security-auditor , a react-specialist , a kubernetes-specialist , a quant-analyst — and let Claude Code dispatch the right expert for every task. So I did the obvious thing. I installed, wired up, and actually used 100 subagents across real work: code review, debugging, test runs, security audits, database analysis, incident triage. I watched which ones Claude actually delegated to, which ones sat inert, and which ones quietly made my main conversation worse . Most got deleted. Not because they were badly written — many were excellent — but because I'd fundamentally misunderstood what a subagent is for . That misunderstanding is the whole point of this article, and I'll get to it before the list. This is the shortlist that survived. Twelve subagents. Out of a h