AI 资讯
AI Agent 市场设计:让 Agent 像 App 一样被交易与编排
AI Agent 市场设计:让 Agent 像 App 一样被交易与编排 App Store 把「软件」变成了可被一键购买、安装、评分的商品,AI 时代对应的实体是「Agent」。一个 Agent = 一段可被复用的提示词 + 工具集 + 知识库 + 模型路由配置。本文讲清楚一个 Agent 市场需要哪些核心机制,以及 IHUI-AI 的实现路径。 一、Agent 市场的产品定义 什么是「可上架的 Agent」 不是所有对话 prompt 都能成为商品。一个可上架的 Agent 必须满足: 可独立运行 :用户购买后能立刻用,不需要再写代码。 可复用 :不同用户用同一个 Agent 都能得到稳定结果。 可定价 :有明确的使用边界(次数 / 时长 / 调用规模)。 可评估 :有客观的质量指标(成功率 / 满意度 / 失败率)。 Agent 定义格式 IHUI-AI 用一份 schema 描述可上架的 Agent: const MarketplaceAgentSchema = z . object ({ id : z . string (). uuid (), name : z . string (), description : " z.string(), " // 核心能力 systemPrompt : z . string (), tools : z . array ( z . string ()), // 引用工具/MCP server knowledgeBases : z . array ( z . string ()), // 绑定 RAG 知识库 modelRouting : z . object ({ default : z . string (), // 默认模型 fallback : z . string (). optional (), // 降级模型 }), // 定价 pricing : z . object ({ model : z . enum ([ " free " , " subscription " , " per_call " , " revenue_share " ]), price : z . number (), currency : z . string (). default ( " CNY " ), trialQuota : z . number (). default ( 0 ), }), // 评估 metrics : z . object ({ successRate : z . number (), avgLatencyMs : z . number (), rating : z . number (). min ( 0 ). max ( 5 ), usageCount : z . number (), }), }); 二、四种定价模型 模型 适用 优点 缺点 免费(Free) 引流、品牌 Agent 易扩散 无直接收入 订阅(Subscription) 高频工具型 Agent 收入稳定 流失需运营 按调用计费(Per Call) 低频高价值 Agent 与成本对齐 用户预算焦虑 分成(Revenue Share) 内容生成型 Agent 创作者激励 结算复杂 IHUI-AI 默认采用 订阅 + 按调用混合 :基础功能订阅包月,超出额度按调用计费,创作者拿 70% 分成。 三、Agent 质量评估:四维评分 简单的「5 星好评」不够,因为容易被刷分。IHUI 用四维加权: 任务成功率(40%) :Agent 完成用户原始任务的比率,由 LLM-as-Judge 自动评估。 用户评分(25%) :真实用户打分,过滤异常分布(全是 5 星或 1 星)。 响应延迟(15%) :首 token 时延 + 总时长,归一化到 [0,1]。 稳定性(20%) :错误率 + 重试率,错误越少分越高。 def agent_score ( metrics ) -> float : return ( 0.40 * min ( metrics . success_rate , 1.0 ) + 0.25 * metrics . user_rating / 5 + 0.15 * ( 1 - min ( metrics . p95_latency / 30_000 , 1 )) + 0.20 * ( 1 - min ( metrics . error_rate / 0.1 , 1 )) ) 这个分数实时更新,作为市场搜索排序的依据。 四、Agent 编排:从单个 Agent 到 Agent 工作流 单个 Agent 的能力有上限。Agent 市场的真正价值在于「让用户像搭积木一样编排多个 Agent」。
AI 资讯
Part 3: The '1.5-Second Trap' Overlooked by AI. Avoiding Account Ban Risks Using Years of Scraping Experience
This article was originally published on e-shikumi-labo . Hello, I'm Shin from e-Shikumi-Labo. This is Part 3 of "Systematized Thinking," where we use AI to build our own tools and independently maintain them. Last time, I talked about creating a system to automatically output Markdown (.md) files to Google Drive simultaneously with appending to a spreadsheet. With list management in a spreadsheet and a comfortable viewing environment in Obsidian established, it was getting very close to completion as a tool. However, as I continued to use it practically, new challenges emerged on the operational front. This time, I will share the risks I faced while transitioning from a "manual button" to "full automation," and the process of evolving into safe code. 1. I Want to Eliminate the "Hassle of Pressing a Button" During the prototype stage, the system was designed so that logs were saved by pressing a button placed on the screen. However, as long as a human operates it manually, there are inevitably limitations. If you are concentrating on the conversation, you might forget to press the save button and close the screen. If the conversation gets long, you might miss past utterances that are no longer displayed on the screen. "If I have the screen open and am conversing, I want it to automatically save in the background without bothering human hands." Thinking this, I asked the AI to write the code for full automation. 2. The Code the AI Produced: "Patrolling the Screen Every 1.5 Seconds" When I consulted the AI, it immediately presented code for full automation. The mechanism was, "Start a timer every 1.5 seconds, check the entire screen in the background, and send any new utterances." When I actually tried it, the logs accumulated automatically as soon as I conversed without pressing the button, and at first glance, it looked like exceptionally well-done full automation. However, I felt something was slightly off regarding this "monitoring on a 1.5-second cycle." 3. The B
AI 资讯
One missing checkpoint can break every approval gate
Approval workflows do not fail only at the model layer. In a production agent, the more common failure is losing the exact paused state that a reviewer was supposed to approve. Why can a saver decide LangGraph approvals? A saver can decide LangGraph approvals because approvals depend on persisted graph state, not just a chat transcript. LangGraph interrupts pause execution inside a node, store the current state, wait until a human decision arrives, and resume the intended checkpoint with Command(resume=...) ; without a saver tied to the same thread_id , the reviewer handoff can resume the wrong point or fail to resume at all . Quick Answer: LangGraph approvals work only when the paused run is checkpointed and resumed through the same thread_id . LangSmith adds the audit layer: each trace is capped at 25,000 runs, and SaaS trace retention is documented as 400 days from ingestion . The practical rule is simple: put the checkpoint before the irreversible action. That means email sends, file writes, deploys, database mutations, support-ticket edits, purchases, payments, outbound messages, and code execution should pause before the side effect. LangChain's HumanInTheLoopMiddleware follows the same shape: inspect tool calls after model output but before execution, then allow an approve, edit, or reject decision against a checkpointed run . "Interrupts are designed to pause graph execution and resume from the saved point," according to the official LangGraph interrupts documentation . For developers, the important part is operational: the approval gate is only trustworthy if the persisted checkpoint and reviewer decision refer to the same run. LangSmith then gives the team evidence that the gate is behaving correctly. Its observability model groups execution into projects, traces, runs, and threads, which lets teams audit latency, rejection reasons, retry count, tool failures, and reviewer decisions instead of debugging from logs alone . The seed video is useful background
开发者
DJI Osmo Pocket 4P review: The best gimbal camera money can't buy
The OG gimbal camera goes "pro" with two lenses, class-leading dynamic range and optical zoom.
AI 资讯
The 3 AM Dashboard: Why Most SaaS Analytics Pages Fail Their Users (And How to Fix Yours)
It's 3 AM. Your customer can't sleep. They open your SaaS product on their phone to check one number — whether their pipeline is healthy, whether something needs their attention before morning. What they see instead is a wall of 47 widgets, three unlabeled charts, and a date picker buried behind a gear icon. They close the tab. They don't come back. This isn't a hypothetical. In 2024, Userpilot benchmarked 62 B2B SaaS products and found that only 37.5% of new users ever reach activation — the point where they actually experience the value they signed up for ( Userpilot User Activation Benchmark Report, 2024 ). The rest poke around a dashboard, get overwhelmed, and leave. A Nielsen Norman Group study found that decision-makers spend roughly 2.3 seconds scanning a dashboard before deciding to engage or abandon it. Your analytics page is the screen where retention is won or lost. And most SaaS companies are losing. The Four Ways Dashboards Fail 1. The Data Dump The most common failure: treating a dashboard like a warehouse. Every stakeholder gets a tile. Three years in, the dashboard has 34 widgets and nobody can find anything. One UX audit of a banking analytics platform found that 11 of 23 displayed metrics were never clicked — four drove 80% of all sessions. After removing 17 widgets, adoption rose 41% in six weeks ( SaaS Dashboard Design: How to Build Dashboards Users Actually Love ). The team asked, "What data should we show?" The right question is: "What decision does this user need to make in the next 30 seconds?" 2. No Default Narrative A dashboard that shows "$42,000 MRR" with no trend arrow, no comparison, and no time period label forces the user to do mental math. A number without context is a snapshot; a number with a trend is a story. Research consistently suggests that 5–7 primary metrics is the maximum before cognitive load degrades comprehension — and for the headline view, 3–5 is ideal ( SaaS Dashboard Design Guidelines ). When different parts of a das
AI 资讯
The Founder-Led Sales Playbook: From $0 to $1M ARR Without Hiring a Single Salesperson
Every bootstrapped SaaS founder hits the same wall. You've built a product. You have organic signups. You're at $3-5K MRR growing 5% per month. At this rate, you'll hit $1M ARR in approximately... never. The conventional wisdom says: hire a salesperson. But you can't afford one. A decent SaaS AE costs $80-120K base plus commission, and the good ones want to sell for funded companies with brand recognition. Here's the good news: you don't need a sales team to reach $1M ARR. You need a system. And you — the founder — are the best salesperson your company will ever have, because you understand the customer's problem better than anyone you could hire. This playbook covers the tools, processes, and scripts to run founder-led sales from zero to a million ARR. Why Founder-Led Sales Wins At $10K MRR, your entire company revenue is $120K per year. Hiring a salesperson at $80-100K base means 70-80% of revenue goes to one person — before ramp time (3-6 months), tools, and leads burned while learning. Meanwhile, you already have the context. You built the product. You can answer any objection without checking with a product team. According to OpenView Partners' SaaS Benchmarks, companies in the $1-5M ARR range with founder-led sales close deals 40% faster than those with early sales hires, primarily because founders can make pricing and scope decisions on the spot. Companies like Bannerbear and many IndieHackers founders built to $1M+ ARR with the founder doing all the selling. It's often optimal. Phase 1: $0 to $10K MRR — Manual Everything Your job is to find the first 10-20 customers who will pay you, use your product, and give you feedback. The Tools ($0-50/month) CRM: A spreadsheet. Notion, Airtable, or Google Sheets. Don't buy a CRM until you have 50+ leads. Email: Your personal email via Google Workspace ($6/month). Meetings: Google Meet (free) or Calendly free tier. Enrichment: Apollo.io free tier or manual LinkedIn research. The Process Step 1: Build a target list of 10
AI 资讯
Handoffs can turn one task into a 15x token bill
Handoffs are useful when a specialist agent needs to take over a task. They also make cost easier to hide, because the bill is spread across graph nodes instead of one visible chat turn. Why can LangGraph handoffs multiply tokens? LangGraph handoffs can multiply tokens because each model-calling node may resend instructions, prior messages, retrieved material, tool returns, summaries, and artifacts, then loops or handoffs repeat that payload for the next agent. Token amplification is the total prompt-plus-completion tokens across a trace divided by a simpler baseline for the same task; Anthropic reported in June 2025 that multi-agent systems used about 15x more tokens than chats while improving an internal research evaluation by 90.2% . Quick Answer: Handoffs raise the token bill when each agent receives copied context instead of a narrow task packet. Anthropic’s June 2025 research system showed the tradeoff clearly: multi-agent runs used about 15x more tokens than chats while scoring 90.2% higher on its internal research evaluation . In LangGraph, the practical issue is observability and budgeting, not whether graphs are bad. The LangGraph project describes the runtime as a way to build stateful, long-running agents with persistence, human control, memory, and debugging support; those same traits make it possible to measure where context grows instead of guessing. "Multi-agent systems are often highly effective at open-ended research tasks, but token usage can be substantial," — Anthropic engineering team at Anthropic The small verified demo below shows the arithmetic behind a 15x bill: a 100-token task becomes 1,500 billed tokens when 5 agents each receive 3 copies of the relevant context . """ Tiny token-accounting demo: handoffs multiply the same task context. """ task_tokens = 100 agents = 5 context_copies_per_handoff = 3 # instructions + task + summary/history direct_bill = task_tokens handoff_bill = task_tokens * agents * context_copies_per_handoff print ( f
AI 资讯
Your Scraper Works Locally but Returns 403 on a Server. Here's Why.
Key takeaways A request is judged on many layers at once — IP reputation, TLS fingerprint, HTTP/2 shape, headers, and how the browser is driven — and failing any one is enough for a 403. Your laptop passes because every layer is consistent with a real home browser; a server changes one (usually the IP) and the inconsistency is the tell. A 403 with no challenge page almost always means you were blocked at the network layer (IP/ASN reputation or TLS/JA3 fingerprint) before any HTML was served — not a credentials or rate-limit bug, so 'add a User-Agent' or 'slow down' won't fix it. The fix order that actually works: get off datacenter IPs (residential/ISP proxies), match a real browser's TLS fingerprint, and spin up a real-browser stealth setup only for the pages that truly need JavaScript — escalate, don't lead with a browser. A proxy only changes your IP; a Linux VPS still leaks a Linux-shaped TLS/JS fingerprint, so 'residential IP + datacenter everything-else' is a contradiction a real home machine never makes — which is why a proxied server can get blocked harder than your laptop. Your scraper runs perfectly on your laptop. You deploy it to a VPS or a CI runner, change nothing in the code, and suddenly every request comes back 403 . It feels like a bug — the code is identical — but it usually isn't. Anti-bot systems judge a request on many signals at once, and moving from your home machine to a datacenter flips several of them at the same time. This post breaks down exactly which signals change, how to tell which one is blocking you, and how to fix it — for authorized access to public data (we'll keep that framing honest throughout; nothing here is about defeating a protection). A request is judged in two stages It helps to know that detection happens in two stages: Stage 1 — before any HTML is served. IP reputation, your TLS handshake, your HTTP/2 settings, and header order are all inspected on the connection itself, passively and cheaply, before your request is e
AI 资讯
The Great Ubuntu Blackout: My 3-Hour Journey to Fix the Darkness
Introduction It was a perfectly normal day. I opened my laptop, ready to get some work done, and then... BAM. A black screen. Not a gentle fade to black, but more like my computer shouting, "I’ve had enough of your crap!" The same operating system that had been working perfectly just five hours earlier had suddenly decided it had had enough of life. I wasn't too worried though. After all, I had ChatGPT on my side. Three hours later... Yeah... my confidence crumbled faster than my phone battery at 2%. What followed was a three-hour rabbit hole involving NVIDIA drivers, multiple Linux kernels, Secure Boot, DKMS, Xorg, GDM, journalctl , systemd , and more terminal commands than I'd like to admit. Somehow, against all odds (and probably a little divine intervention), we managed to fix it. And honestly? I enjoyed every minute of the chaos. It was like a wild adventure—except with more curse words and less danger. So I decided to document the entire debugging journey—not just because it might help someone who runs into the same issue, but also because I deserve a little sympathy after spending three hours arguing with my laptop. (And if the solution seems painfully obvious to you... please let me enjoy my victory. Don't take this away from me.😤 The Problem After rebooting my laptop, I was greeted with just a black screen. No login screen, no desktop… just nothing.** At first, I tried to enter TTY using Ctrl + Alt + F3, but that wasn’t working either. Since I wasn’t able to reach TTY directly, I had to take a different route. By editing the GRUB boot entry and booting into multi-user.target , I forced Linux to start in text-only mode, giving me access to a terminal.** For this, I edited the GRUB boot entry and appended systemd.unit=multi-user.target to the end of the kernel command line (after quiet splash ). That was the first breakthrough, though. The operating system wasn’t completely dead… only the graphical interface was failing to wake up. First Clues and Initial Ass
AI 资讯
From RAG to Agentic AI. How I Added LangGraph to My Local
In my previous article , I built a fully local RAG assistant Ollama, ChromaDB, LangChain, all running in Docker. It answered technical support questions by searching through documentation and citing sources. It worked. But after using it for a while, I noticed something uncomfortable: it treated every question the same way . Ask it "how to close monthly payroll?" it searches the docs. Fine. Ask it "the server crashes at startup" it also searches the docs. Less fine. Ask it something completely outside the documentation it searches the docs. Useless. A real support technician doesn't do that. They first assess the situation, then decide what to do: look it up, run a diagnosis, or escalate to a human. My RAG had no such judgment. That's what this article is about how I evolved the system into an Agentic AI architecture using LangGraph, where the assistant first decides which strategy to use , then acts accordingly. The Core Limitation of Classic RAG Classic RAG is a linear pipeline. Every query follows the exact same path: Question → Embed → Retrieve → Prompt → LLM → Answer No branching. No decision-making. No memory between steps. This works perfectly for procedural questions where the answer lives in the docs. But technical support involves at least three distinct scenarios: Scenario Example Best strategy Procedural question "How do I create an account?" Search documentation Known error code "ERR-COMP-001 appears" Lookup error database Unknown incident "Server crashes, no idea why" Diagnose + escalate if needed A single RAG pipeline handles the first case well and the other two poorly. The solution is to add a layer of reasoning before retrieval. What Agentic AI Adds The shift from RAG to Agentic AI comes down to one thing: the system plans before it acts . Instead of one fixed pipeline, you have: Question ↓ Classifier (what kind of question is this?) ↓ ├── Procedural → RAG Agent (search docs) ├── Error code → Diagnostic Agent (lookup + LLM analysis) └── Complex → D
AI 资讯
Scraping platform costs: measure successful rows, not browser minutes
A scraping job usually fails in boring ways: the browser hangs, a selector starts returning empty strings, a login expires, or the target site returns a captcha halfway through the run. The awkward part is that many platforms still bill you for the work done before the failure. If you run enough jobs, that difference shows up both in your invoice and in the amount of defensive code you need around the scraper. Billing by compute time changes how you build A lot of scraping platforms charge for runtime. Apify, for example, uses compute units: memory multiplied by time. A browser-heavy actor running for ten minutes with 2 GB of RAM consumes roughly a third of a compute unit before any actor-specific result fees. That model is reasonable from the provider side. Chromium processes are expensive. Proxies cost money. Retries use resources. But as the caller, you care about a different unit: did I get the rows I needed? The hard part is that runtime billing makes cost hard to know before execution. A job that normally takes 30 seconds might take 8 minutes when a site slows down. A job that returns malformed data can still count as successful from the platform's point of view. A job that fails after rendering 200 pages still consumed browser time. If your pipeline runs once a day, that may be fine. If it runs continuously, you probably want a local cost model that tracks outcomes, not just requests. type ScrapeRun = { jobId : string ; target : string ; startedAt : string ; finishedAt ?: string ; status : " queued " | " running " | " succeeded " | " failed " ; rowsExpected ?: number ; rowsReceived ?: number ; billedUnits ?: number ; }; function isUsefulResult ( run : ScrapeRun ) { if ( run . status !== " succeeded " ) return false ; if ( run . rowsExpected && ( run . rowsReceived ?? 0 ) < run . rowsExpected * 0.9 ) { return false ; } return ( run . rowsReceived ?? 0 ) > 0 ; } function costPerUsefulRow ( run : ScrapeRun ) { if ( ! isUsefulResult ( run )) return Infinity ; ret
AI 资讯
LangGraph isn't cheaper than LangChain — unless you opt out of its defaults
LangGraph isn't cheaper than LangChain — unless you opt out of its defaults Cost-audit series, episode 4. This series began with an AI agent that burned 136M tokens overnight → . When LangChain deprecated ConversationBufferMemory (the subject of episode 1 in this series), the official migration path was LangGraph. The pitch: explicit state management, you control exactly what flows where. More expressive, more controllable. It is — but only if you reach for the controls. The default state model in LangGraph has the same unbounded-growth problem as the memory it replaced. Teams migrating to escape ConversationBufferMemory's cost curve often land on an identical curve, with new graph complexity on top. This audit shows exactly where the default grows, what it costs, and what opt-outs exist. The default: MessagesState + add_messages The quickstart in LangGraph's own docs uses this pattern: from langgraph.graph import StateGraph , MessagesState def my_node ( state : MessagesState ): messages = state [ " messages " ] response = llm . invoke ( messages ) # sends ALL messages to the LLM return { " messages " : [ response ]} graph = StateGraph ( MessagesState ) graph . add_node ( " agent " , my_node ) MessagesState is a TypedDict with a single key, messages , backed by the add_messages reducer. Here's what that reducer does: # langgraph/graph/message.py — add_messages (def at line 18; merge loop below) def add_messages ( left : Messages , right : Messages ) -> Messages : # ... (coerces left/right to lists of BaseMessage) ... left_idx_by_id = { m . id : i for i , m in enumerate ( left )} merged = left . copy () ids_to_remove = set () for m in right : if ( existing_idx : = left_idx_by_id . get ( m . id )) is not None : if isinstance ( m , RemoveMessage ): ids_to_remove . add ( m . id ) else : merged [ existing_idx ] = m # same id → update in place else : merged . append ( m ) # new id → APPEND (the list grows) merged = [ m for m in merged if m . id not in ids_to_remove ] retu
AI 资讯
AI-Native Redesign: The Principles Don't Change — Only the Machinery Does
AI assistance disclosure: This article was drafted with the help of Claude. All technical content, design decisions, code references, and screenshots reflect production systems I designed and operate at airCloset; the prose was revised by me prior to publication. Hi, I'm Ryan , CTO at airCloset (a fashion-rental subscription service based in Japan). "Everything changes with AI" is the prevailing mood. My experience building and then running an internal AI platform (cortex) points the other way. The principles don't change at all. Only the machinery does. This post is about what I've come to treat as principle, what I've concluded should be broken, and the thinking behind that split. Disclaimer : "cortex" in this article is the internal codename for the AI platform built in-house at airCloset. It is unrelated to existing commercial services like Snowflake Cortex or Palo Alto Networks Cortex. I've written about the individual pieces before: code-graph , product-graph , db-graph , biz-graph , AI-Observability , the auto-review harness , and Self-Healing . This post isn't about any of them. It's about the design principle sitting behind all of them, one abstraction level up, more essay than build log. The principle, in one sentence: how do we make accurate information accessible? It's an old question. Libraries, legal case books, encyclopedias, search engines — every era has had its own answer using whatever tools that era gave it. Even the technology revolutions people call "paradigm shifts" mostly just changed the means . The underlying question didn't move. Now AI has arrived, and my read (probably not a controversial one) is that its shift is at least on the scale of the internet, possibly larger. As with every previous paradigm shift, the means of answering "how do we make accurate information accessible?" will get redesigned from the ground up. That's what this post is about: AI-Native Redesign — a view where you rebuild the whole design with AI treated as a given
开发者
Experts warn current Starship heat shield tech is a "dead end" for rapid reuse
NASA has not made substantial investments in thermal protection research for decades.
科技前沿
Canon EOS R6 V review: A pro vlogging camera at a mirrorless price
Canon's EOS R6 V is a video-focused hybrid camera that's outstanding for vlogging.
AI 资讯
The Distributed Systems Challenge of Post-Quantum Cryptography
Encrypted data stored in cloud archives today will outlive the mathematical algorithms guarding it. In enterprise architectures that handle long-term records, like construction risk logs or employee compliance platforms, data retention schedules often span twenty to thirty years. When building cloud pipelines that move this information across services, we depend heavily on asymmetric encryption, which is a security method using one public key to lock data and a separate private key to unlock it. Standard public-key algorithms rely on mathematical problems that are nearly impossible for classical computers to solve within a reasonable human timeframe. Quantum computing changes this equation entirely. Quantum computers leverage quantum mechanics, the physical rules governing subatomic particles, to perform calculations at speeds fundamentally unimaginable with traditional silicon processors. While powerful quantum systems are still in development, the security threat to distributed systems exists today. Hostile actors do not need to crack modern security algorithms in real time. Through a pattern known as Harvest Now, Decrypt Later, adversaries can capture and store encrypted network traffic right now. They simply wait until future quantum hardware becomes capable of running the formulas required to decrypt that stolen history. For software architects, preparing for post-quantum cryptography, which refers to new mathematical encryption algorithms designed to withstand quantum attacks, is far more than a simple library swap. It is a deep distributed systems migration challenge. The primary operational hurdle is payload size and computational overhead. Quantum-resistant algorithms require significantly larger digital keys and payload headers than the standards we rely on today. When cryptographic payloads expand, every component of a distributed platform feels the ripple effect. Message queues experience higher bandwidth demands. Database indexes inflate. Memory consump
开发者
Rotating Residential Proxies in Python: requests, Scrapy & Sticky Sessions
When you scrape at any real volume, the bottleneck is rarely your code — it's the target site's rate limiting and IP bans. Rotating residential proxies solve this by routing each request through a different real-user IP. Here's how to wire them into requests and Scrapy in Python, including the sticky-session trick most tutorials skip. The proxy URL format A residential proxy is just an authenticated HTTP/SOCKS endpoint. With a pool gateway, you target a country and control session behavior through the username , not separate endpoints: http://USERNAME_country-us_session-a1b2c3_lifetime-30:PASSWORD@proxy.gproxy.net:1000 country-us — exit country (ISO code) session-a1b2c3 — a sticky-session id; reuse it to keep the same IP , change it to rotate lifetime-30 — how many minutes that session's IP stays fixed Basic request through a rotating proxy import requests USER = " USERNAME " PWD = " PASSWORD " def proxy ( country = " us " , session = None , lifetime = 30 ): tag = f " _country- { country } " if session : tag += f " _session- { session } _lifetime- { lifetime } " url = f " http:// { USER }{ tag } : { PWD } @proxy.gproxy.net:1000 " return { " http " : url , " https " : url } # New IP on every call (no session id): r = requests . get ( " https://api.ipify.org?format=json " , proxies = proxy (), timeout = 30 ) print ( r . json ()[ " ip " ]) Run it in a loop and you'll see a different IP each time — the gateway rotates automatically when no session id is present. Sticky sessions: keep one IP across requests Some flows (login, multi-step checkouts, paginated results behind a cookie) break if your IP changes mid-session. Pin the IP by passing a stable session id: import uuid sess = uuid . uuid4 (). hex [: 8 ] # one id for the whole flow p = proxy ( country = " de " , session = sess , lifetime = 30 ) s = requests . Session () s . proxies . update ( p ) s . get ( " https://example.com/login " ) s . post ( " https://example.com/login " , data = {...}) # same exit IP When you
AI 资讯
KRACK: How WPA2 Wi-Fi Encryption Was Broken by Reusing a Key
In October 2017, researcher Mathy Vanhoef published an attack that broke WPA2, the encryption that had protected almost every Wi-Fi network on the planet for over a decade. The surprise was how it worked. KRACK did not guess your Wi-Fi password or brute-force any key. It tricked your device into installing a key it had already used, and that single mistake unraveled the encryption. WPA2 replaced the badly broken WEP standard in 2004 and quickly became the baseline for wireless security. For thirteen years it held up well. The passphrase-based version most homes use (WPA2-Personal) was vulnerable to offline password guessing if you chose a weak passphrase, but the protocol itself was considered sound. KRACK, short for Key Reinstallation Attack, was different. It targeted a flaw in the WPA2 standard itself, which meant every correct implementation was affected. The four-way handshake, briefly When a device joins a WPA2 network, the client and the access point run a four-message exchange called the four-way handshake. Both sides already share a secret (derived from the passphrase or from an enterprise authentication server). The handshake uses that shared secret to agree on a fresh session key, the Pairwise Transient Key, that will actually encrypt the traffic for this session. The important part is message three. The access point sends message three to tell the client the key is ready, and the client responds with message four and installs the key. Once installed, that key encrypts frames using a counter, called a nonce or packet number, that increments with every frame. The security of the encryption depends on one rule: a given key must never encrypt two different frames with the same nonce. The reinstallation trick Wi-Fi is a lossy medium. Messages get dropped. So the standard says that if the access point does not receive message four, it retransmits message three. When the client receives a retransmitted message three, it reinstalls the same key and, critically,
AI 资讯
Why I Chose Slot Hashes Over VRF for Fair Random Selection on Solana
When I set out to build a provably-fair random selection system on Solana, the obvious choice for randomness was a VRF (Verifiable Random Function). Instead, I built the system around Solana's SlotHashes sysvar with a commit-reveal scheme. Here's why, and what I gave up to get there. The problem A fair-selection system needs a winner (or set of winners) chosen in a way that's fair, and just as important that participants can check for themselves without taking anyone's word for it. VRF services (Switchboard, ORAO, etc.) solve the fairness part well: they produce randomness that's unpredictable in advance and cryptographically provable after the fact. But they come with a dependency on an oracle, a fee per request, and a proof that most users will never actually verify they'll trust it because the crypto math says they can, not because they did. I wanted something a participant with no crypto background could check in a browser console. The approach: commit-reveal with slot hashes The core idea: commit to the participant list before you know the randomness, then derive the randomness from a slot hash you couldn't have predicted at commit time. rust fn derive_randomness(target_hash: &[u8; 32], participant_root: &[u8; 32]) -> [u8; 32] { let mut combined_seed = [0u8; 64]; combined_seed[..32].copy_from_slice(target_hash); // slot hash at reveal combined_seed[32..].copy_from_slice(participant_root); // Merkle root, locked at commit solana_keccak_hasher::hash(&combined_seed).to_bytes() } The flow: Commit: participant list is finalized and hashed into a Merkle root; this is written on-chain. Wait: a target slot in the future is chosen as the reveal point. Reveal: once that slot passes, its hash is pulled from SlotHashes and combined with the committed root to derive the randomness. Select: the randomness deterministically picks winners from the participant set; winners get their own Merkle root and proofs. Every draw ends up with an audit record like: rust pub struct AuditR
AI 资讯
HollowGraph Malware Uses Microsoft 365 Calendar Events as Dead-Drop C2 Channel
What Happened On July 20, 2026, cybersecurity firm Group-IB disclosed a new espionage implant dubbed HollowGraph that hijacks compromised Microsoft 365 mailboxes to run a command-and-control (C2) channel hidden inside calendar events. The malware attaches encrypted files to calendar entries dated May 13, 2050 — far enough in the future that a mailbox owner would never scroll to them — and retrieves operator instructions from the same dead drop. All traffic moves through the Microsoft Graph API, making the activity indistinguishable from legitimate M365 usage. At least 12 systems have been infected, with three actively communicating with the threat actor between June 3 and July 9, 2026. The indicators point to a targeted espionage campaign focused on Israeli organizations . Technical Analysis HollowGraph is a lightweight .NET DLL that supports only two commands: GET and SEND . To receive tasking, it queries the compromised mailbox's calendar for an event titled in the format "Event ID: <7-char-taskID>", downloads the attached file, and decrypts it using RSA and AES-256-GCM. To exfiltrate data, the implant creates a new calendar entry titled "Boss{..}ID{..}" and uploads stolen files encrypted with the attacker's public RSA key. The Group-IB research team described the mailbox calendar as a "covert dead-drop," with HollowGraph retrieving commands from events scheduled within a fixed one-hour window between 22:00 and 23:00 UTC on the far-future date. The hybrid encryption scheme uses separate RSA key pairs for inbound and outbound channels, keeping them cryptographically isolated. A second, unencrypted channel runs over DNS tunneling . HollowGraph refreshes its Microsoft Entra ID (Azure AD) credentials by querying IPv6 AAAA records from the attacker-controlled domain cloudlanecdn[.]com . Each returned IPv6 address yields 14 usable payload bytes, which the malware assembles and decodes as UTF-8 text to update its logAzure.txt configuration file — a file masquerading as a