惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News and Events Feed by Topic
GbyAI
GbyAI
博客园 - Franky
宝玉的分享
宝玉的分享
Blog — PlanetScale
Blog — PlanetScale
Google DeepMind News
Google DeepMind News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
人人都是产品经理
人人都是产品经理
Microsoft Azure Blog
Microsoft Azure Blog
The Register - Security
The Register - Security
腾讯CDC
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
I
InfoQ
The Cloudflare Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
有赞技术团队
有赞技术团队
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
F
Full Disclosure
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Vercel News
Vercel News
博客园 - 【当耐特】
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Schneier on Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Project Zero
Project Zero
量子位
M
MIT News - Artificial intelligence
Stack Overflow Blog
Stack Overflow Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
美团技术团队
Attack and Defense Labs
Attack and Defense Labs
C
Cybersecurity and Infrastructure Security Agency CISA
T
The Blog of Author Tim Ferriss
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Troy Hunt's Blog
Google Online Security Blog
Google Online Security Blog
罗磊的独立博客
P
Proofpoint News Feed
Schneier on Security
Schneier on Security
Spread Privacy
Spread Privacy
S
SegmentFault 最新的问题
L
LINUX DO - 最新话题
Simon Willison's Weblog
Simon Willison's Weblog
爱范儿
爱范儿
博客园 - 聂微东
A
About on SuperTechFans
PCI Perspectives
PCI Perspectives
D
Docker

Hacker News

randoFont GitHub - onehorizonai/silo-terminal: A dark phosphor Apple Terminal profile inspired by the sealed systems and green-blue screens of Silo. GitHub - unihosted/unifi-os-server-docker Show HN: Onboard-CLI–a fast developer tool built in Go uses AST and LLM Show HN: Finterm.ai Finance CLI for Claude Code and Codex Show HN: Codex Explorer,一款用于 Codex CLI 的本地会话管理器 Pylon — full-stack framework for coding agents GitHub - Corgea/Sighthound: Corgea's rule-based SAST scanner Kastra | Execution Governance for AI Systems devthropology.com Embersent — Know Exactly Who Read Your Document GodUI — UI Collection for Modern Interfaces Show HN: Reverse-engineering web apps into agent tools GitHub - Kuberwastaken/subagentmaxxing: Drive OpenAI Codex & Cursor CLI coding agents as subagents with the same ergonomics as native Claude Code subagents (grok-4.5, composer-2.5, gpt-5.5). Uniform run/fanout CLI + Claude Code skill. Aside Today I’m launching papercrane-cli: a BI tool built for Claude Code | Papercrane Blog Strata - Guess the City from a 3D Map a dark terminal Blocks.ai | Connect your agent to the world. Noticky — Sticky Notes & Always-on-Top Windows for Mac Make the hard day easier for the people you love CASHFLOW — Debt Network Optimizer 0 A.D.: Empires Ascendant FormGrid - Create Delightful Forms & Surveys for Free Codapult — Everything Your SaaS Needs, Already Wired Together LaTeX Diff Viewer - GitHub Marketplace LinguaGuessr analog.watch Estimania — Daily Estimation Game I Replaced Whisper with Parakeet on a $55/Month CPU Server. Here Is What Actually Happened. HyperSwitcher – Mac App & Window Switcher CLERC-DATA/epee · Datasets at Hugging Face GitHub - gladiaio/gladia-cli EvenKeel — your money coach BareMetalRT — Bare Metal AI Build a Second Brain That Actually Remembers Why It Changed Tokenstead - Find AI Models for Your Hardware Fideby - Standing by the people you trust, when you can rubber duck GitHub - forgedculture/legibility-field-kit GitHub - ronak-create/FableCut: Zero-dependency browser video editor that AI agents can drive — JSON timeline, MCP + REST, live-reloading UI GitHub - BuceaGeorgia/VIRENA: A minimal Vision-Language-Action model you can read: frozen CLIP + a tiny head on ManiSkill PickCube. Runs on a Mac, no GPU. Fehu - Apps on Google Play GitHub - fresswolf/Slopera: The browser for the slop era Release Kiyeovo 1.0.0 · Realman78/Kiyeovo Noema — AI Company Analysis GitHub - hamidi-dev/opentab: 📊 Browse your AI coding spend in the terminal — OpenCode, Claude Code, Codex & more GitHub - sgInnora/wc2026-prediction-ledger: Receipt-verified AI prediction ledger for World Cup 2026: pre-kickoff sha256-locked forecasts scored vs results, with calibration + market baselines. Live: goalpulse.io/open-data GitHub - michaelwrites67-ctrl/yogen: 予言 Yogen — a 500-agent AI swarm that debates your idea and predicts the outcome. Self-host free with your own Anthropic key. GitHub - teddytennant/wizard: Self-extending autonomous agent in one Rust binary. One-line install, any provider (OpenAI-compatible, Anthropic, xAI) or fully local via llama.cpp, live /evolve self-modification, MCP, messaging gateway, built-in bench arcaide.foo Show HN: Android Developer Verification Package blacklisted in Aurora Store OpenDescent: Private messaging for normal people GitHub - tarunlnmiit/autopilot-jobhunt: AI job agent: scans 130+ careers pages nightly, scores every role against your resume with an LLM (0–100), alerts you on Telegram, and drafts tailored cover letters + resumes. Free & open source. 18 Words - Daily Word Challenge The State of US Local Government Accessibility 2026 flow - Real-time network throughput dashboard for the terminal. - Terminal Trove Battle LLM Robots GitHub - robesris/ffvii-realtime: Speed up Final Fantasy VII (Rebirth / Remake / Revelation) Tactical Mode slow-motion so combat plays at real-time speed Agent Sessions - Local History for AI Coding Agents Scrutora — code, cloud & consent compliance in one platform SoulOS Tutorials GitHub - gaemi/agentic-fc: Open-source football management simulation played by AI agents through MCP and watched through a TUI console. GitHub - talalalrwas/ocr-grab: Flameshot clone that adds OCR. GitHub - JustVugg/colibri: Run GLM-5.2 (744B MoE) on a 25GB-RAM consumer machine — pure C, zero deps, experts streamed from disk. Tiny engine, immense model. 🐦 GitHub - saifmukhtar/kinetic figment computer linear.gratis - Free Linear Client Feedback Forms GitHub - atelier-ws/atelier: Runtime for coding agents. Models are getting smarter, but a model is only as capable as the environment supporting it. Atelier is that environment. https://atelier.ws Atlas · Tomesphere | Tomesphere Codenames Generator GitHub - lyfeninja/lyfeninja_blkseal_python_sdk: Lightweight Python client for signing and verifying digital content using lyfe.ninja's BlkSeal product powered by BlkBolt™. Designed for zero dependencies, simple integration, and exact content verification. DateTimeMate OpenScreenShot — Full-page screenshot & annotation tool for Chrome 38-0 — Build Your Premier League Dream Team Cyrinx — data over sound, measured GitHub - BhaveshThapar/mcp-audit HN Work GitHub - Northwood-Systems/foreman: Self-hosted LLM gateway. Cost effective, deterministic, and fast. Secure and private by default. A Visualization Language for the AI Era GitHub - weirdGuy/kastor: Declarative language and toolchain for AI agents: define agents, tools and prompts in HCL, then compile to frameworks or manage them on hosted platforms with plan/apply semantics. Abralo - Run multiple Claude Code agents in one window GitHub - mehranzand/repofleet: RepoFleet is an issue-centered CLI tool for managing Git workflows across multiple repositories. Pug — Open Source Product Analytics Chiptune Radio — Aleph Void, LLC Free Mermaid Live Editor & Diagram Maker GitHub - hirasso/html-obfuscator: Obfuscate emails, phone numbers, and other sensitive data in PHP. Invisible to humans, hidden from bots until they interact. Davit — a native macOS UI for Apple containers GitHub - rowboatlabs/rowboat: Open-source AI coworker, with memory Yamanote.fun PostgreSQL on AWS: Size & Benchmark EC2 Instances GitHub - Rodiun/frugon: Free, local, open-source LLM cost analyzer — see where your LLM bill leaks, on your machine. WhimFiles - Find Any File in Seconds Neil the Seal GitHub - animesh-94/Onboard-CLI: An AST-powered, local-first CLI that visualizes complex system architectures and enforces architectural boundaries via instant Git hooks. ridealong — live London trains Clusy | Agent-Native Notebook for ML and Data Science snowscroll · Instagram, without the spiral. GitHub - vishal-dehurdle/state-harness: Runtime safety net for LLM agents. Detects token spirals, kills doomed tasks early, tells you exactly why. Rust core, Python SDK. pip install state-harness GitHub - DO-SAY-GO/freelang: I love freelang
Agent Draw: An agent draws while you talk, built on TLDraw
James Daniel Whitford · 2026-07-06 · via Hacker News

We recently built 2draw, a Drawful-style game where players draw on a shared canvas and race to guess each other's drawings, on tldraw, an infinite-canvas SDK for React.

We started wondering what it would take to put an agent in that loop, as an opponent or a rival guesser, and dug into how an agent could read and draw on a tldraw canvas. That research turned into:

Agent draw, a tool that lets an agent draw to the canvas for you while you present.

Here you can see the agent assisting me in my demo presentation of a third grade chemistry class.

You can try it right now, or grab the source:

Agent Draw is an agent that draws while you present

Drag a rectangle on the canvas, say what you want inside it, and by the time you look back it's there, drawn by an AI agent while you kept talking. Drag a few rectangles in a row and they queue up, each drawing in turn. All of this happens on an infinite canvas tool called tldraw.

What is tldraw?

tldraw is an infinite-canvas SDK for React: the same editor API a user drives with a mouse, an agent can drive in code, creating shapes, moving them, drawing arrows between them.

We did not build our agent from scratch. tldraw already publishes an official Agent starter kit that draws and arranges shapes through a chat panel, backed by a Cloudflare Worker. We built Agent Draw on top of that.

How good is an agent at drawing?

A simple composition built on top of tldraw's primitives, rectangles, diamonds, arrows, is something most models handle well. A more intelligent model tends to get more ambitious with the composition, and is better at placement on the canvas. We tested this by giving each model the same two requests in one session: draw a decision diagram, and draw a person playing cricket.

claude-opus-4.8 handled both well, a clean decision diagram built from primitives, and, more interestingly, a fully realised cricket scene sketched with the pen tool:

claude-opus-4.8's freeform pen sketch of a stick figure batsman swinging at a cricket ball, with stumps and a wicket, drawn entirely with the pen tool rather than geometric primitives

Where it struggles

That was claude-opus-4.8, one of the more capable models available. The result looks different with a smaller model behind the same requests.

A smaller model settles for less

Give the same two requests to a smaller model, and the ambition drops off fast. claude-haiku-4.5 matches Opus on the decision diagram, but for the cricket request it stays with primitives instead of reaching for the pen, and settles for a simpler, static composition with a label rather than a dynamic sketch:

claude-haiku-4.5's cricket player built from simple primitives (rectangles and circles for the body, bat, and ball) with a text label, a less ambitious composition than Opus's freeform sketch

A weaker model can give up on the task

Drop down further to google/gemini-2.5-flash-lite, and it seems to give up early on both requests:

google/gemini-2.5-flash-lite's incomplete result: a half-finished figure with disconnected lines for arms, next to an unfinished decision diamond left over from an earlier request

How we made agent draw

The whole feature is a new canvas tool, a speech pipeline, a serialized draw queue, and a prompt section, and here is each piece, with the actual code from the repo.

Capturing the region you draw

Dragging out a region with the Agent draw tool, showing the dashed selection brush on the tldraw canvas

tldraw tools are state machines. You subclass StateNode and define child states; tldraw routes pointer events to whichever state is active. Our AreaCaptureTool has three states (idlepointingdragging) and does its real work on pointer-up, when the dragged rectangle is final:

class AreaCaptureDragging extends StateNode {
static override id = 'dragging'

private bounds: BoxModel | undefined = undefined

override onPointerUp() {
this.editor.updateInstanceState({ brush: null })
if (!this.bounds) throw new Error('Bounds not set')
// Hand the captured rectangle (in page coordinates) to the capture session.
startCaptureSession(this.bounds)
this.parent.transition('idle')
}

updateBounds() {
if (!this.initialPagePoint) return
const currentPagePoint = this.editor.inputs.getCurrentPagePoint()
const x = Math.min(this.initialPagePoint.x, currentPagePoint.x)
const y = Math.min(this.initialPagePoint.y, currentPagePoint.y)
const w = Math.abs(currentPagePoint.x - this.initialPagePoint.x)
const h = Math.abs(currentPagePoint.y - this.initialPagePoint.y)
// Show tldraw's native selection brush while dragging.
this.editor.updateInstanceState({ brush: { x, y, w, h } })
this.bounds = { x, y, w, h }
}
}

We get the live selection-brush rectangle for free by writing to editor.updateInstanceState({ brush }), the same instance state tldraw's own select tool uses. The bounds are in page coordinates, so they stay correct no matter how the user has panned or zoomed.

Listening while you talk

The moment a capture starts, we open the mic. AreaRecorder is a thin wrapper over the browser's MediaRecorder, deliberately with no knowledge of the agent or transcription, just start() and stop():

export class AreaRecorder {
async start(): Promise<void> {
this.stream = await navigator.mediaDevices.getUserMedia({ audio: true })
const recorder = new MediaRecorder(this.stream, { mimeType: this.mimeType })
this.chunks = []
recorder.ondataavailable = (event) => {
if (event.data.size > 0) this.chunks.push(event.data)
}
recorder.start()
this.recorder = recorder
}

async stop(): Promise<Blob> {
// ...stop the recorder, release the mic, resolve with the recorded clip...
return new Blob(this.chunks, { type: this.mimeType || 'audio/webm' })
}
}

Turning speech into text

The audio blob is posted to a new /transcribe route on the same Cloudflare Worker that already serves the agent. The route just forwards the audio to Mistral's Voxtral transcription model and returns the text, so a server-held key covers every demo visitor by default:

export async function transcribe(request: IRequest, env: Environment) {
const form = await request.formData()
const file = form.get('file')

// A visitor's own key (if they've added one) takes priority over the server's.
const mistralKey = request.headers.get('x-mistral-api-key') || env.MISTRAL_API_KEY

const outForm = new FormData()
outForm.append('file', file)
outForm.append('model', 'voxtral-mini-transcribe-2507')

const mistralResponse = await fetch('https://api.mistral.ai/v1/audio/transcriptions', {
method: 'POST',
headers: { Authorization: `Bearer ${mistralKey}` },
body: outForm,
})

const data = (await mistralResponse.json()) as { text?: string }
return new Response(JSON.stringify({ text: data.text ?? '' }), {
headers: { 'Content-Type': 'application/json' },
})
}

Handling more than one drawing at a time

Several captures in flight at once on the canvas, each with its own status pill showing recording, queued, or drawing

This is the part that makes multiple captures work. You can drag a second rectangle while the first is still drawing, and the captures draw in order rather than fighting over the canvas. The whole thing is a module-level state machine over a tldraw atom: a single active recorder, a FIFO queue, and a single-consumer worker that handles one session at a time.

Starting a new capture auto-stops the one still recording and queues it:

export function startCaptureSession(bounds: BoxModel): string {
// Drawing a new capture ends the audio of the one still recording.
if (recordingId) finalizeRecording(recordingId)

const id = nextId()
sessions.set([...sessions.get(), { id, bounds, status: 'recording' }])

const rec = new AreaRecorder()
recorder = rec
recordingId = id
rec.start().catch(/* surface a mic-permission error on the session */)
return id
}

The consumer drains the queue one session at a time, moving each through transcribingdrawing. Serializing here is the whole point: the agent runs one request at a time, so a newer capture simply waits its turn:

async function processQueue(): Promise<void> {
if (processing) return // single consumer
processing = true
try {
while (queue.length > 0) {
const id = queue.shift() as string
const session = getSession(id)
const blob = pendingBlobs.get(id)
// ...skip if dismissed / no audio / agent not ready...

patchSession(id, { status: 'transcribing' })
const text = await transcribe(blob)
// ...error out here if the chosen model's provider needs a key the visitor hasn't supplied...

patchSession(id, { status: 'drawing' })
await requestDrawInArea(agentRef, text, session.bounds)

removeSession(id) // clear the overlay for this capture
}
} finally {
processing = false
}
}

An earlier version tried to stream the mic live and draw as you talked. It was laggy and the value was fuzzy, so we cut it for this discrete capture-then-speak model, and the queue is what replaced the old "two captures cancel each other" overlap bug.

Making the agent keep drawing until the job is done

Each session's transcript and bounds go to requestDrawInArea. The interesting decision here is that we use the starter kit's full agentic loop, agent.prompt, not the single-turn agent.request. prompt keeps taking turns on its own until the model has nothing left to add, so the model finishes the entire drawing in one call instead of drawing one shape and stopping.

export async function requestDrawInArea(
agent: TldrawAgent,
text: string,
bounds: BoxModel
): Promise<number> {
const area = { type: 'area' as const, bounds, source: 'user' as const }
ensureMode(agent, 'working')
const before = agent.editor.getCurrentPageShapeIds().size
try {
await agent.prompt({ message: buildAreaMessage(text), contextItems: [area] })
return agent.editor.getCurrentPageShapeIds().size - before
} finally {
ensureMode(agent, 'idling')
}
}

An earlier version hand-rolled a continue-loop with extra linter passes to force a complete drawing, because a single-turn request only drew one shape. Once we confirmed agent.prompt finishes the whole drawing on its own, all of that scaffolding got deleted.

Making it faster

The starter kit's working mode ships with a fairly broad action list. For a fixed-region draw two of those actions were costing a full LLM round-trip each without improving the result.

setMyView moves the camera to frame the shapes the agent just drew. For a canvas chat panel that makes sense, but for area capture the viewport is irrelevant, the user wants to see what was drawn, not have the camera jump around. The problem is that setMyView interrupts the current turn and triggers a re-request, adding a round-trip.

review runs the starter kit's lint system: it checks for overlapping shapes, text that overflows its box, and similar issues, then schedules a follow-up turn to fix them. Again, useful in a chat panel, but for a one-shot area draw it just adds another model call at the end.

Removing both from the working mode's action list roughly halved the number of model calls per capture. The change is two lines in AgentModeDefinitions.ts:

// review and setMyView removed — each forces an extra round-trip per draw
// without helping the fixed-region result. Utils stay registered for other modes.
actions: [
ThinkActionUtil.type,
CreateActionUtil.type,
PenActionUtil.type,
// ... rest of actions ...
]

The utilities stay registered so they remain available to the chat panel. They are just not offered to the agent when it is drawing inside a captured area.

Teaching the model to draw, not transcribe

Left: the spoken request transcribed as a paragraph of text. Right: the same request drawn as a clean labelled diagram instead, not a wall of transcribed text

The last piece is a prompt. Left alone, a model handed a sentence of speech tends to write that sentence on the canvas as a wall of text. We wrote a "Drawing inside a captured area" section for the starter kit's system prompt that does two things: it forces the model to assess what visual form actually fits the request, and it forbids dumping the transcript verbatim:

Choose the visual form that best fits the request and immediately emit
create/pen actions — do not ask for clarification, do not stop to think
without drawing:

- A specific named shape ("draw a red circle", "a star"): draw exactly that.
- A single object or illustration: draw it well, not a multi-box diagram.
- A definition or explanation: draw a labelled diagram with keyword labels,
not the spoken sentence as a block of text.
- A diagram or process: labelled nodes with arrows.
- A chart: for quantitative or comparative content.

If the request is ambiguous, make your best interpretation and draw it anyway.
Never stall — always emit at least one shape.

It also insists the model build the complete result in one turn ("the user does not reply between actions, so anything you defer to a follow-up message will never happen"), which pairs with the agent.prompt decision above.

Adding the tool to the toolbar

The 'Agent draw' tool added to the tldraw toolbar, next to tldraw's built-in tools, with its own icon

Finally, the tool is registered through tldraw's standard override API, so "Agent draw" sits in the toolbar next to the built-in tools with its own icon and keyboard shortcut:

const tools = [AreaCaptureTool, TargetShapeTool, TargetAreaTool]

const overrides: TLUiOverrides = {
tools: (editor, tools) => ({
...tools,
'area-capture': {
id: 'area-capture',
label: 'Agent draw',
kbd: 'a',
icon: agentDrawIcon,
onSelect() { editor.setCurrentTool('area-capture') },
},
// ...Pick Area / Pick Shape unchanged...
}),
}

<Tldraw
licenseKey={import.meta.env.VITE_TLDRAW_LICENSE_KEY}
tools={tools}
overrides={overrides}
components={components}
/>

That is the entire feature: a tool that captures a rectangle, a recorder, a worker route for transcription, a queue, one call into the agent loop, a couple of trimmed actions for speed, and a prompt section. Everything else, the canvas, the agent, the action system, the streaming backend, came from the starter kit.

Note on licensing: our code is MIT, like the starter kit it's built on, so it runs locally for free. The tldraw SDK itself is under a separate, proprietary license, and needs a license key for any public deployment. Non-commercial projects can get a free hobby license from tldraw.