AI 资讯
How to Build an AI Agent That Asks Permission First (Nuxt + AI SDK 7)
Introduction I did something stupid. I built a superhero-themed Nuxt app, connected it to an Anthropic model through Amazon Bedrock , and gave it a tool that deletes files from my computer. In fact, if I wasn't careful, it could have deleted all my files! The first time I tried it, I didn't use any sort of approval mechanism. And as you expected it just deleted things. Then I looked into how my coding agent works, and I learned about tool approvals. I learned that AI SDK 7 has a tool approval at the model-call level. It works by pausing for an approval, showing an approval window, and then deleting it. I then put Kiro CLI behind the same interface using Agent Client Protocol (ACP). Watch the full video on YouTube . Prerequisites You need: Node.js 22 or later. AI SDK 7 requires Node.js 22 and uses ECMAScript modules (ESM). npm 11 or another package manager that works with Nuxt 4. AWS credentials available through the standard provider chain. Access to an Amazon Bedrock model in your AWS Region. The AWS CLI if you want to list the inference profiles available to your account. An authenticated Kiro CLI installation for the optional ACP section. Step 1: Create the Nuxt app Create the project and install the versions used in the recorded demo: npx nuxi@latest init nuxt-agent-approval cd nuxt-agent-approval npm install \ nuxt@4.5.2 \ vue@3.5.41 \ ai@7.0.66 \ @ai-sdk/vue@4.0.66 \ @ai-sdk/amazon-bedrock@5.0.57 \ @aws-sdk/credential-providers@3.1111.0 \ @nuxt/ui@4.10.0 \ zod@4.4.3 npm install -D @iconify-json/lucide@1.2.123 Register Nuxt UI and expose the Amazon Bedrock settings through server-side runtime config: // nuxt.config.ts export default defineNuxtConfig ({ modules : [ ' @nuxt/ui ' ], css : [ ' ~/assets/css/main.css ' ], runtimeConfig : { awsRegion : process . env . AWS_REGION ?? ' us-west-2 ' , bedrockModelId : process . env . NUXT_BEDROCK_MODEL_ID } }) Add the two Nuxt UI imports: /* app/assets/css/main.css */ @import "tailwindcss" ; @import "@nuxt/ui" ; You can c
开发者
Engineering: Dreams, or Self-Actualization?
At what point did you start to think you were an engineer? An engineer. What a lofty,...
AI 资讯
Your verifier will be gamed by the thing it verifies
Two agents finish the same task and report back. Fixed. The migration now handles null values. It wrote the code. It never ran it. Fixed. Added a null-handling layer, refactored the migration runner into a strategy pattern, and introduced a validation module. Every word true. All of it works. None of it asked for, and that strategy pattern is now yours to maintain forever. Point your code-review agent at both. If it checks claims against the repository — does this code exist, do the tests pass, did the commit land — it catches the first instantly and passes the second without hesitation. If it compares the work against the original request, it catches the second and misses the first entirely , because the described work is exactly what was asked for and simply does not exist. Neither reviewer is broken. They answer different questions. Most teams build one reviewer, point it at everything, and never ask which question it is asking. So I built reviewers that named what they were hunting. That worked, briefly, and then taught me something worse. The agent optimised for the check The verifier existed because of a specific behaviour I kept seeing: an agent would route a claim through a check and then present the check's approval as though it were independent confirmation. Not fabrication — something subtler. Authority laundering. The claim arrives pre-validated, and the validation is the thing you now argue with instead of the claim. Once a verifier existed, the behaviour adapted. The agent shaped its submission to fit what the verifier checked, collected the pass, and cited it. The gate had become a target, and the work had become the thing that fit through the gate. I first saw this in one model. Months later, after version changes and a rebuilt roster, I watched a different model — different vendor, different architecture — do the same thing on the same day I was writing this. Which is why "know your model's failure mode" is weak advice Models do fail in characterist
AI 资讯
Why Google Won't Index Your Pages: 4 GSC Fixes
Originally published on echoeffect.net . If you have been inside Google Search Console recently and clicked into the Pages report (previously called Index Coverage), you may have seen a section titled "Why pages aren't indexed." That list tells you exactly which URLs Google found on your site but chose not to add to its search index, and the reason for each one. This is not abstract SEO theory. Pages that are not indexed cannot rank. If Google is excluding pages from your site, you are losing search visibility you should have, and the reason is usually fixable once you understand what Google is actually telling you. This post covers the four most common "not indexed" statuses small business websites encounter, what each one means in plain terms, and the exact steps to resolve it. A quick note before diving in: Some pages on your site should not be indexed. Thank-you pages, admin pages, internal search result pages, and duplicate filter pages are examples where non-indexing is correct. Before fixing any of these errors, confirm the flagged URL is actually a page you want in Google's index. 1. Page With Redirect What it means: Google followed one of your URLs and landed on a different URL because a redirect was in place. The original URL is not indexed. Only the final destination URL is eligible to be indexed. This status is usually caused by one of three things: Old URLs still listed in your XML sitemap that have since been redirected (common after a site redesign or domain migration) HTTP versions of pages listed in your sitemap when the live site runs on HTTPS Trailing-slash inconsistencies, where your sitemap lists yoursite.com/page but the server redirects to yoursite.com/page/ The redirect itself is not necessarily a problem. A 301 redirect is the correct way to permanently move a page. The issue is that Google's crawler is spending time and crawl budget following chains to find the real URL, and your sitemap or internal links are pointing to the wrong address.
AI 资讯
Startup or Enterprise? How to Pick the Right AI API Stack
Look, startup or Enterprise? How to Pick the Right AI API Stack Let me set the scene for you. A few months back, I was chatting with two friends on completely opposite ends of the AI spectrum. One was bootstrapping a side project on pizza and prayers, wondering if he could afford to add an LLM to his SaaS without going bankrupt. The other was leading engineering at a mid-sized fintech, sweating bullets because his CTO wanted enterprise-grade guarantees before signing a single contract. Same problem on paper: "we need an AI API." Completely different universes in practice. Here's how I'd actually walk each of them through it — and why the generic guides you'll find on the internet miss the mark. The Misconception That Trips Everyone Up I want to be honest with you about something. Most AI API guides assume both audiences want the same thing at different scales. That's wrong. Dead wrong. A startup founder I know burned through two weeks trying to wire up DeepSeek's direct API last quarter. He gave up not because the tech was hard, but because he didn't have a Chinese payment method, didn't want to verify with a Chinese phone number, and got stuck in a KYC loop. Meanwhile, an enterprise architect I talked to last month was spending months negotiating with OpenAI's sales team on annual contracts for committed-use pricing — when all he wanted was a predictable API endpoint with a real SLA behind it. The lesson? The "go straight to the provider" advice is a non-starter for a lot of people, and nobody's talking about why. Let me show you what actually matters depending on which side of the fence you're on. What Startups Actually Need (And Don't) Let me break this down. If you're building a startup — early stage, scrappy, maybe pre-seed or seed — your AI API checklist looks something like this: Cost matters more than perfection You want to experiment with multiple models without signing 12 contracts You need to ship this week, not next quarter Your "compliance team" is just
AI 资讯
The hard part of batch date conversion isn't formatting — it's deciding what `01/02/2024` means
I used to think a bulk date converter was basically a dropdown wrapped around a date library. Paste a bunch of rows, pick YYYY-MM-DD , done. Then you look at real exports from spreadsheets, CRMs, logs, and old internal tools and realize the problem isn't "formatting" at all. It's triage. Some rows are obvious. Some are malformed. Some have month names. Some came from a CSV with five unrelated columns. And then there's the classic cursed input: 01/02/2024 , which is either January 2 or February 1 depending on who produced the file. The Vue component behind this tool is interesting because it doesn't pretend that ambiguity goes away if you call the right parser. It models that ambiguity explicitly. It starts by assuming uploaded files are messy, not clean One thing I liked in the source is that it doesn't treat file input as a single happy path. If you upload a TXT file, it works line by line. If the upload looks CSV-ish, it switches into a tiny parser and then tries to figure out which column is actually the date column. The CSV split logic is manual instead of using a naive line.split(",") , which matters because quoted commas are a real thing in exports: const splitCsvLine = ( line ) => { const result = []; let cur = "" ; let inQuotes = false ; for ( let i = 0 ; i < line . length ; i ++ ) { const ch = line [ i ]; if ( ch === ' " ' ) { if ( inQuotes && line [ i + 1 ] === ' " ' ) { cur += ' " ' ; i ++ ; } else { inQuotes = ! inQuotes ; } } else if ( ch === " , " && ! inQuotes ) { result . push ( cur ); cur = "" ; } else { cur += ch ; } } result . push ( cur ); return result . map (( s ) => s . trim ()); }; After that, it doesn't ask the user to map columns immediately. It scores each column by counting how many cells look like dates, then auto-selects the best candidate: for ( let c = 0 ; c < maxCols ; c ++ ) { const count = dataRows . filter (( r ) => isLikelyDateCell ( r [ c ])). length ; columns . push ({ index : c , header : headerRow ? headerRow [ c ] : "" }); i
AI 资讯
Firefox’s Smart Window promises a better AI browser
Starting today, AI chats in Firefox's Smart Window AI browsing mode can pull from current web info and show source links in chat responses through a partnership with Exa. Smart Window can also now automatically suggest tab groups and show visual previews of pages you previously visited when you search your browsing history using natural […]
AI 资讯
I built a PDF merger that never uploads your files — here's how published: false
MergePDF is a 100% client-side PDF tool. No backend, no uploads, no sign-up. Here's the architecture, the tricky parts, and why privacy is a feature, not a setting. Every tax season, the same thing happens. Someone in my family asks me to merge a few PDFs. They Google "merge PDF." They click the first result — a slick, friendly-looking site. They upload their tax returns to a server they've never heard of. That bothered me. So I built MergePDF. It merges, splits, rotates, and rearranges PDF pages — and your files never leave your browser. No backend. No sign-up. No ads. No tracking. iLovePDF uploads your tax returns. We don't. This post is about how it works, the parts that were harder than I expected, and why "client-side only" is a design philosophy, not just a technical choice. The pitch in 30 seconds Drop one or more PDFs onto the page. You get a grid of page thumbnails — real, rendered previews of every page. Drag to reorder. Click to select. Rotate, delete, extract a range. Merge everything into one file, or split into single-page PDFs zipped up. Download. Done. Your browser does all of it. There is no server processing documents. There isn't even a server to process documents. The stack It's a Next.js app, but honestly Next.js is just the host here. The interesting parts are all client-side libraries doing real work: No database. No API routes. No auth. No analytics. The only thing in localStorage is your theme preference. Drag-to-reorder that doesn't fight tap-to-select This one took three attempts. The requirement: Tap a thumbnail → select it (emerald ring) Shift-tap → select a range Long-press + drag → reorder Swipe on mobile → scroll the grid (don't drag) The conflict: if the whole card is the drag handle, taps get swallowed. If only a tiny grip icon is the handle, nobody finds it (especially on mobile, where there's no hover). So split produces a ZIP. fflate's zip packages every single-page PDF into one download. Rotations are honored here too — each spl
AI 资讯
I generated 8,664 SEO pages. Google indexed them. I got 9 clicks.
I run a small tech-interview-prep site. It has 8,664 individual pages, one per concept — each with a real question, what it's actually testing, a model answer and the mistake that sinks candidates. Programmatic SEO, the whole playbook. Here's what 28 days of Google Search Console says: Impressions 6,511 Clicks 9 CTR 0.14% Average position 45.9 Pages with at least one impression 1,575 of 8,664 (18%) Nine clicks. In a month. From nearly nine thousand pages. I want to walk through this honestly, because the conclusion I reached is not the one I expected, and it's not the one most posts about programmatic SEO land on. What I assumed was wrong My working theory for weeks was "Google isn't indexing them." That's the standard programmatic-SEO failure story: you publish thousands of pages, Google decides your new domain hasn't earned the crawl budget, and most of them sit in Search Console under Discovered — currently not indexed forever. And early on that was true. A few weeks ago only 6 pages had ever received an impression. It's now 1,575. Google is indexing them, steadily, without me doing anything new. The crawl budget arrived on its own schedule. The clicks did not. The actual failure mode Here's the distribution that explains everything. Across 1,206 distinct queries: Position Share of queries 1–10 12% 11–20 6% 21–50 23% 51+ 59% Median position: 58. That's page six of the search results. Nobody has ever been to page six of the search results. So the pages aren't missing from the index. They're in the index, ranked below anything a human will scroll to. Indexed and invisible are close to the same thing, and the second one is more annoying because the dashboard fills up with numbers that look like progress. 6,511 impressions is real. It's also what position 58 produces: Google shows your result to enough people that you see the impression, and none of them scroll far enough to see it. The queries are the tell These are my top queries by impressions: 11 imp pos 52.2 com
AI 资讯
Mobile Gameplay Performance Optimization
MOKSHA — v0.1.1 Devlog Date: 2026-08-18 Milestone: v0.1.1 — https://github.com/weirdcodesofficial/MOKSHA/milestone/11 Highlights Major mobile-focused performance work: reduced per-frame CPU/GPU cost in render path. Replaced hot trig math with a lookup table (LUT) to remove repeated Math.sin/cos calls. Cached per-frame gradients and reduced expensive shadowBlur calls to lower GPU blur passes. Added quality-tier controls and explicit render-state resets for more predictable mobile behaviour. v0.1.1 release PR merged. Merged pull requests (summary) PR #147 — perf(render): replace remaining Math.sin/cos with lutSin/lutCos Replaced ~25 per-frame trig calls in drawScene() with reads from the existing 2048-entry radian LUT (affects ring ticks, pulses, orbit waves, arc heads, timer pill pulses, etc.) — reduces CPU trig cost significantly. https://github.com/weirdcodesofficial/MOKSHA/pull/147 PR #145 — render: Done gradient caching. Implemented caching/baking for commonly created gradients and offscreen sprites (pickup glow, naama, chakravaata, rein gradient buckets) to avoid per-frame gradient allocations and GPU work. https://github.com/weirdcodesofficial/MOKSHA/pull/145 PR #144 — render: quality tier control, explicity reset, 40 shadowBlur calls wr… Added device/quality-tier checks to disable or lower shadowBlur on low-end devices; isolated shadowBlur via save()/restore() and explicit ctx.shadowBlur = 0 resets to avoid leaks. GPU blur pass count reduced. https://github.com/weirdcodesofficial/MOKSHA/pull/144 PR #146 — V0.1.1 (release PR) — bump / release merge. https://github.com/weirdcodesofficial/MOKSHA/pull/146
AI 资讯
How to Compress a GIF Without Losing Quality (2026 Guide)
Let's be honest about why you're here. You have a 4MB animated GIF that's slowing down a product page, bouncing back from an email attachment limit, or getting rejected by an ecommerce backend that caps images at 2MB. Or maybe a client sent you a loop that's 15MB and you need it under 1MB for a Slack header. The good news: you can usually cut a GIF's file size by 70–90% without anyone noticing the difference. The bad news? You have to stop thinking about GIFs as images and start thinking about them as video. Here's the practical guide to compressing GIFs in 2026, using only free browser-based tools. No uploads to shady servers, no software installs, just math and smart tradeoffs. Why GIFs get so big (and why your 4MB file is normal) GIF is a 1987 format. It was designed for simple graphics on dial-up internet, not for 4K animated logos. To understand why it bloats, you need one mental model: A GIF is a video pretending to be an image. Here's what happens under the hood: Limited palette: A GIF can only store 256 colors per frame. That's 8-bit color. Your screen displays millions of colors, so the GIF has to approximate. The real problem is how it stores those colors. Frame-by-frame storage: Unlike MP4, which stores only the changes between frames, a GIF stores every single frame as a full image . A 100-frame animation at 800x600px is 100 full-size images stacked on top of each other. Uncompressed data: GIF uses LZW compression, which is weak by modern standards. It works well on flat colors but fails on gradients, noise, or photographic content. A 10-second screen recording with a subtle gradient? That's a 20MB GIF waiting to happen. The math: A 500x500px, 30fps, 3-second GIF has 90 frames. Each frame is roughly 500x500x3 bytes (RGB) = 750KB raw. Before compression, that's 67.5MB of raw data. LZW might get it down to 4–8MB. That's why your file is huge. It's not a bug; it's the format being honest about its limitations. The three real levers to shrink a GIF You can't
AI 资讯
AI Observability Explained: What It Is and How It Works
Traditional monitoring rests on one quiet assumption that nobody ever writes down: the same input gives you the same output. Something breaks, you replay the request, you watch it break again, you fix it. Now send the same request to a model twice. You get two different answers, and neither one of them threw an error. AI observability is the practice of recording what happened inside an AI system on every request: the prompt, the model version, tokens, cost, latency, tool calls, and a judgement of whether the output was any good. Monitoring tells you the service is up. Observability tells you why it answered that way. That gap is the whole story here. Why your current monitoring stack misses all of this Your existing setup is watching for crashes. Status codes, error rates, p99 latency, memory. All of it is designed around the idea that a broken thing looks broken. An AI feature failing looks nothing like that. It returns HTTP 200 in 900ms, with grammatically perfect prose that happens to be wrong, or that quietly ignored the document you retrieved for it, or that called the refund tool when the user only asked a question. Your dashboard sees a healthy service, because by every measure it has, the service is healthy. And there are whole categories of failure your stack has no field for. It has nowhere to put "this response cost 14 cents", or "the model version changed under us last Tuesday", or "the retrieved context was garbage". Those are not infrastructure facts, and standard telemetry was never built to carry them. Something has to hold those fields instead, which is the entire reason this tooling exists. My team uses Bifrost , so I will use it as the example throughout this post. It's an open-source AI gateway from Maxim, so anything I claim about what it records per request is something you can go check line by line. Most tools here put their telemetry story on a marketing page and stop there. What one AI request actually looks like when you trace it This is t
AI 资讯
TypeScript 6.0 Strict Function Types: Why Contravariance Breaks Your Existing Callbacks
TypeScript 6.0 Strict Function Types: Why Contravariance Breaks Your Existing Callbacks This article was written with the assistance of AI, under human supervision and review. Most TypeScript migration failures stem from a single misunderstood compiler flag: strictFunctionTypes . The pattern that breaks production is deceptively simple—a callback that accepts a base type where the consumer expects a derived type. TypeScript 6.0 enables strict mode by default, which means codebases that never configured contravariance checking will fail to compile overnight. The failure mode here is subtle but expensive. A callback registered to an array method expects Animal , but the implementation passes Dog . Pre-6.0 TypeScript allowed this through bivariant parameter checking. Post-6.0, the compiler rejects it as unsafe. Teams scramble to fix hundreds of type errors without understanding the underlying variance rules, often choosing any or incorrect casts that introduce runtime bugs. The distinction between function properties and method signatures becomes critical—one enforces contravariance, the other permits bivariance for historical reasons. %% alt: Bivariant checking allows derived types where base types are expected The correct approach requires understanding contravariance: function parameters must accept types that are the same or less specific than what the function signature declares. When strictFunctionTypes activates, TypeScript enforces this rule for function properties but not method signatures. The solution is not to weaken types with any , but to restructure callbacks using proper variance-aware patterns or switch to method syntax where bivariance is intentional. %% alt: Contravariant checking enforces parameter safety at compile time This matters because the TypeScript 6.0 ecosystem assumes strict mode. Third-party libraries ship types built for contravariance. Disabling strictFunctionTypes to silence errors creates a type system that diverges from reality, wher
AI 资讯
Five AI coding tools, five completely different ways to break
I've now routed five different AI coding tools through a proxy layer. Each one broke differently. None of them told me why. Writing this partly as a reference for myself, partly because the failure modes turn out to be genuinely interesting — they say a lot about how these tools are built. Claude Code: reads config once, then never again The simplest of the five. Config lives in ~/.claude/settings.json , two keys get modified: env.ANTHROPIC_BASE_URL env.ANTHROPIC_AUTH_TOKEN The failure mode: it reads that file exactly once, at startup. Change it while a session is running and nothing happens. No warning, no reload. This is the single most common "the switch is on but nothing works" report, across every tool. Close all windows, open a fresh one. One thing I appreciate: it only touches those two keys, backs up the original, and restores it exactly when you flip the switch off. Codex: doesn't read the model from your request This one is architecturally weird and cost me an hour. Every other tool specifies which model it wants in the request. Codex doesn't. It picks from its own internal model catalog. Consequence: if you don't explicitly select a model, it sits on a default internal GPT model that the market can't serve. And you don't get "please select a model" — you get a string of failures with no stated cause. The config it writes: ~/.codex/config.toml → model_provider, [model_providers.asale], model, model_catalog_json ~/.codex/auth.json → OPENAI_API_KEY Note model_catalog_json . That's the part that makes your selection show up in the app's model menu. And the desktop app reads that catalog at startup , so a model written while it's running won't appear until you restart. Two separate restart requirements stacked on each other. Credit where due: it preserves your existing comments and formatting in config.toml . Not every tool does. Gemini CLI: loses to your own shell config Config goes into ~/.gemini/.env . Two keys added, nothing else touched. The failure mode
AI 资讯
Building a Client-Side Zodiac Calculator: When "Just Use an API" Isn't the Answer
I recently found myself in one of those classic developer rabbit holes. A friend asked me if I knew their Chinese zodiac sign, and instead of just Googling it like a normal person, I thought: "I could build a tool for this." Because apparently I enjoy reinventing wheels. The twist? I wanted it to work entirely in the browser. No API calls, no server, no database. Just a date input and some JavaScript logic. The challenge was figuring out how to accurately compute Chinese zodiac signs, the Chinese lunar calendar year, and the traditional Ganzhi (干支) system without pulling in a massive calendar library. The Problem with Existing Solutions My first instinct was to search for an API. There are plenty of Chinese calendar APIs out there, but they all had issues: Most require API keys and rate limiting Many are Chinese-language only, which is fine for me but not great for a broader audience They're overkill for what should be a simple calculation Some have questionable accuracy for historical dates I also looked at JavaScript libraries like lunar-javascript and chinese-calendar . They're comprehensive, but they're also huge. For a simple "what's my zodiac sign" tool, pulling in a 100KB+ library felt like using a flamethrower to light a candle. The Math Behind the Madness Here's what I discovered: the Chinese zodiac and Ganzhi calculations are surprisingly straightforward if you understand the underlying math. The Zodiac: Simple Modulo Arithmetic The 12 Chinese zodiac animals follow a cycle that aligns with the 12-year Jupiter cycle. The calculation is embarrassingly simple: const ZODIAC = [ ' 鼠 ' , ' 牛 ' , ' 虎 ' , ' 兔 ' , ' 龙 ' , ' 蛇 ' , ' 马 ' , ' 羊 ' , ' 猴 ' , ' 鸡 ' , ' 狗 ' , ' 猪 ' ]; const zodiac = ZODIAC [( year - 4 ) % 12 ]; That's it. The year 4 AD was the first year of the Rat, so everything since then follows a simple modulo pattern. The Ganzhi System: Two Interlocking Cycles The Ganzhi (干支) system combines the 10 Heavenly Stems (天干) with the 12 Earthly Branches (地支
开发者
🚀 30 React.js Interview Questions You Should Know Before Your Next Frontend Interview ⚛️
30 React.js Interview Questions You Should Know Before Your Next Frontend Interview ⚛️ Whether you're preparing for a frontend interview or simply want to brush up on your React.js knowledge , this guide covers 30 real-world, scenario-based React interview questions that interviewers frequently ask. The goal isn't just to memorize definitions. These questions are designed to help you understand how and when to apply React concepts in real-world applications . 📌 Bookmark this article and come back to it during your next interview preparation session. 📚 What We'll Cover In this guide, we'll explore questions around: Conditional rendering API calls and side effects Form validation Performance optimization State management Component re-rendering Keys and lists Dark mode Dynamic components useEffect vs useLayoutEffect Large-list optimization And much more... 1. How do you handle conditional rendering in React? Conditional rendering allows you to render different UI based on application state or conditions. You can use standard JavaScript techniques such as: if...else Ternary operators Logical && Example { isLoggedIn ? < Dashboard /> : < Login />} 💡 Interview Tip For simple conditions, a ternary operator or && is usually sufficient. For more complex conditions, consider moving the logic outside the JSX to keep the component readable. 2. You need to fetch API data when a component mounts. What's the best way to do it? 💡 Key Concept The typical approach is to perform the API request inside a useEffect hook when the component needs to fetch data after rendering. A common pattern is: useEffect (() => { // Fetch API data }, []); The empty dependency array indicates that the effect is intended to run after the initial render. Note: In modern React applications, the best approach can also depend on the framework or data-fetching library you're using. 3. How would you handle form validation in React? A common approach is to use controlled inputs and perform validation during even
AI 资讯
🤖 AI agents are becoming “digital employees”
SpaceXAI recently introduced Grok Bot, an always-on AI-agent service designed to work more like an autonomous teammate. The agents have their own cloud computer environment and can log into applications, websites and tools to perform multi-step tasks. They can also operate in parallel and coordinate with other agents. The product is entering a market that already includes competing agentic workplace products from OpenAI, Anthropic and Microsoft. Traditional chatbot: User ↓ Question ↓ LLM ↓ Answer And Now Agent: Goal ↓ LLM ↓ Plan ↓ Tool ↓ Observe ↓ Reason ↓ Tool ↓ Validate ↓ Continue ↓ Result * But there's a major problem : * Giving an AI agent access to: Email Slack GitHub CRM Cloud Browser Databases Internal documents creates a huge identity and security problem. An agent with permission to send an email or modify production infrastructure effectively becomes another privileged identity. About the Author -> I am Ashutosh Maurya , a Senior Full-Stack Developer ** with 6+ years of experience in high-performance UI development and the MERN stack. I specialize in building scalable architectures like Schooliko and **AI-integrated platforms . My goal is to bridge the gap between complex backend logic and seamless frontend experiences.
AI 资讯
How to Turn Latitude and Longitude into an Address with JavaScript
Sometimes you have GPS coordinates like: 40.7128, -74.0060 But coordinates alone are not very useful to most users. They usually want to know something much simpler: What place is this? The process of converting latitude and longitude into a human-readable address is called reverse geocoding . In this article, we'll build a simple reverse geocoding example with JavaScript. What Is Reverse Geocoding? Normal geocoding converts an address into coordinates: New York, NY ↓ 40.7128, -74.0060 Reverse geocoding does the opposite: 40.7128, -74.0060 ↓ New York, NY, United States This is useful for location tools, GPS applications, travel websites, delivery systems, photo location tools, and map interfaces. Reverse Geocoding with JavaScript For a simple example, we can use the OpenStreetMap Nominatim reverse geocoding endpoint. async function reverseGeocode ( lat , lon ) { const url = `https://nominatim.openstreetmap.org/reverse` + `?lat= ${ lat } &lon= ${ lon } &format=jsonv2` ; const response = await fetch ( url ); if ( ! response . ok ) { throw new Error ( " Reverse geocoding failed " ); } const data = await response . json (); return data ; } reverseGeocode ( 40.7128 , - 74.0060 ) . then ( data => { console . log ( data . display_name ); }) . catch ( error => { console . error ( error ); }); The returned data usually contains a readable location name together with structured address information. Display the Address on a Page We can turn the example into a small browser tool. <input id= "lat" placeholder= "Latitude" > <input id= "lon" placeholder= "Longitude" > <button onclick= "findAddress()" > Find Address </button> <p id= "result" ></p> <script> async function findAddress () { const lat = document . getElementById ( " lat " ). value ; const lon = document . getElementById ( " lon " ). value ; const result = document . getElementById ( " result " ); try { const url = `https://nominatim.openstreetmap.org/reverse` + `?lat= ${ lat } &lon= ${ lon } &format=jsonv2` ; const res
AI 资讯
7 MCP Tool-Schema Mistakes That Make AI Agents Less Reliable
AI agents can only use tools as reliably as those tools are described. That’s why I built ToolReady AI —a free tool that reviews MCP and AI-agent tool schemas, identifies reliability problems, and recommends specific fixes. A function might work perfectly when a developer calls it directly, yet still fail when an agent has to decide when to call it, which arguments to provide, and what values are safe. In many cases, the problem is not the underlying API. It is the tool schema placed between the API and the model. Here are seven issues worth checking before releasing an MCP or AI-agent tool. A description that is too vague Descriptions such as "Searches documents" do not give an agent enough routing context. The description should identify the supported content, expected result, important limits, and a clear use case. Better: «Search indexed support documents and return the most relevant text excerpts. Use this when answering questions about product setup or troubleshooting. Do not use it for account-specific or real-time billing information.» No boundary conditions A useful description should also explain when the tool should not be used. Exclusions help an agent distinguish similar tools and avoid calls that cannot succeed. Examples include: Do not use for personal account data. Do not use when the user requests current inventory. Do not use for destructive actions without confirmation. Undocumented inputs An input name such as "query", "id", or "limit" may seem obvious to its author, but the agent still has to guess the required meaning and format. Each property should explain: What the value represents The expected format A realistic example Any important constraints Missing required fields If the schema does not identify the minimum necessary inputs as required, an agent may send an empty or incomplete call that cannot produce a useful result. For example: { "type": "object", "properties": { "query": { "type": "string", "description": "Natural-language search q
AI 资讯
We Tested 4 Text-to-Speech Engines on 12,000 Live Healthcare Calls — Here's Which One Patients Actually Trust
Last quarter, we ran our production voice AI receptionist — Loquent — across four different TTS engines simultaneously, split-testing real patient calls at dental and healthcare clinics. The results surprised us: the most "natural sounding" engine in demos performed the worst with actual patients. Why We Ran This Test At Autor, we've been running Loquent in production for over a year now. It handles thousands of automated calls per month for healthcare and dental clinics across Canada — booking appointments, answering insurance questions, handling after-hours triage. The voice is the product. If patients don't trust the voice, they hang up, and the clinic loses a booking. When we first built Loquent, we picked our TTS engine the way most teams do: we generated a few sample clips, played them for ourselves, and went with the one that sounded best in a quiet office. That worked fine until we started digging into our call analytics and noticed something weird. Our completion rate — the percentage of calls where patients actually finished the full interaction instead of hanging up or asking for a human — was hovering around 74%. Good, but not great. We suspected the voice itself was part of the problem. So we designed a proper A/B test. Not a demo comparison. A production comparison on live calls. The Setup We tested four TTS engines across 12,247 calls over 8 weeks. Each engine handled roughly equal volume, randomly assigned at call start. All other variables stayed constant: same prompts, same Anthropic Claude backbone for conversation, same Twilio infrastructure, same clinics. The four engines: Engine A : ElevenLabs (Turbo v2.5) — our existing production engine Engine B : OpenAI TTS (tts-1-hd) — the model most teams default to Engine C : Deepgram Aura — optimized for real-time, low-latency use cases Engine D : A newer entrant we'd been evaluating (under NDA, so I can't name it) We measured five things: Completion rate — did the patient finish the full call flow? Time