Siri AI Is Becoming Apple’s Everything Tool
Apple’s revamped Siri is more than a voice assistant; it’s now the backbone of the iPhone user experience. You can try it now through the iOS 27 public beta.
找到 2955 篇相关文章
Apple’s revamped Siri is more than a voice assistant; it’s now the backbone of the iPhone user experience. You can try it now through the iOS 27 public beta.
When an autonomous agent gets an email address of its own, the first question your security team asks isn't "can it send mail?" It's "can you prove, six months from now, exactly what it said and to whom?" That's a different problem from "does it work." A demo that fires off a few support replies looks great in a sprint review. But the moment a real customer says "your bot promised me a refund," or a regulator asks for the complete record of what an automated system told a data subject, you need a defensible trail — an immutable record of every outbound and inbound message the agent touched, captured outside the mailbox the agent can also delete from. I work on the Nylas CLI, so the terminal commands below are the exact ones I reach for. But the architectural point here is provider-agnostic and it's the part most "AI email" tutorials skip: the live mailbox is not your audit log. It's mutable, it has retention limits, and the same agent that sends mail can also trash it. If your only record of what the agent did lives in the inbox, you don't have an audit trail — you have a working copy. What "audit-log everything" actually means There are two stores in this design, and keeping them separate is the whole point. The live mailbox — the Agent Account grant. Messages flow in and out here. It's queryable, it's real-time, and it's mutable . Flags change, messages move folders, things get trashed. On the free plan it's also retention-limited: 30 days for the inbox, 7 days for spam. The audit store — your system. An append-only, write-once log keyed by message_id and thread_id . Nothing in it is ever updated or deleted in normal operation. This is the record you hand a reviewer. The audit store is the thing you build. Nylas gives you the two capture points — the send response and the inbound webhook — but the immutability is your responsibility. That means a WORM (write-once-read-many) object store, an append-only table with no UPDATE / DELETE grant for the app role, or a has
Most multi-tenant SaaS apps that send email do it from one shared identity. There's a notifications@yourapp.com , every customer's mail flows through it, and the tenant is just a from_name you stamp on the subject line or a footer you swap out. That's fine until it isn't — until Tenant A's spam complaints drag down Tenant B's deliverability, until a reply from a customer lands in a single firehose inbox you now have to fan back out, until one tenant wants a stricter send cap than another and you realize you built none of that into the data model. So let's not share. Let's give every tenant its own real mailbox — a dedicated Agent Account per customer, each with its own grant_id , its own send identity, its own policy and limits, grouped into its own workspace. Not one inbox with a thousand label hacks. A thousand inboxes, isolated by construction. I work on the Nylas CLI, so the terminal commands below are the exact ones I reach for when I'm wiring this up. Every step gets the two-angle tour: the raw curl call and the nylas command that does the same thing. Why per-tenant beats one shared sender The shared-sender model fails along a few predictable seams. Per-tenant Agent Accounts close each one: Deliverability blast radius. When everyone sends from one address, one tenant's bounce rate and spam complaints poison the reputation everyone shares. Per-tenant accounts — and, if you want, per-tenant domains — keep one customer's bad behavior from sinking the rest. Inbound that actually belongs to someone. A shared sender means replies come back to one mailbox and you're left correlating them to tenants by hand. When each tenant has its own grant, an inbound message.created event already carries the grant_id . The routing is done before your handler runs. Per-tenant policy and limits. Different customers, different rules. A trial tenant capped at a low daily send; an enterprise tenant with a higher quota and longer retention. With a shared sender you'd build all of that y
Most teams test email by not testing it. The send path gets a mock — expect(transport.send).toHaveBeenCalledWith(...) — and everyone agrees that's "good enough." The receive path gets skipped entirely, because there's no honest way to assert on a real inbox from a test runner. So the one part of your system that talks to the outside world over an unreliable, asynchronous, third-party channel is the part with the least coverage. That's backwards. The reason email is hard to test isn't the sending. It's the asserting . You can fire POST /messages/send all day, but to prove the message actually left, rendered correctly, and arrived with the body you expected, you need a real mailbox you control — one you can read programmatically and throw away when the run finishes. Shared Gmail test accounts almost get you there, but they bring OAuth on the runner, catch-all races between parallel workers, and a 90-day token that expires the night before a release. This post is about a different fixture: a disposable Agent Account created at the start of a CI run and deleted at the end. You mint a real mailbox per run (or per test), point your application at it, send and receive real mail, assert on the actual message body, and tear the whole thing down. No OAuth. No shared inbox. No leftover state. What an Agent Account gives you here An Agent Account is just a Nylas grant with a grant_id . That's the whole trick, and it's worth saying plainly because it's what makes this pattern cheap: an Agent Account works with every grant-scoped endpoint you already know — Messages, Drafts, Threads, Folders, Attachments, Webhooks. There's nothing new to learn on the data plane . If you've ever called GET /v3/grants/{grant_id}/messages , you already know how to read a test inbox. The difference from a normal grant is provisioning. A regular grant needs a real human to complete an OAuth flow. An Agent Account is created with a single API call — no OAuth screen, no refresh token, no human. It's a m
Most "AI email agent" demos end with a triumphant send . The model writes a reply, the code POSTs it, and a real message lands in a real stranger's inbox. That's a great demo and a terrible production default. The moment your agent can send mail with nobody watching, you've handed an LLM a corporate email address and the standing authority to use it. One hallucinated price, one confidently wrong refund promise, one apology to the wrong customer, and you're explaining to legal why a bot signed an email as your company. There's a boring, durable fix that predates AI by decades: don't send — draft. Stage the message, put a human in front of it, and only send once someone with a name and a pulse approves. Email systems have had a "Drafts" folder forever for exactly this reason. The Nylas Drafts API turns that folder into something better — an approval queue your agent writes into and your reviewers drain. This post builds that queue. The agent creates a draft, a human reviews the pending drafts, and an approved draft gets sent byte-for-byte unchanged . No re-rendering, no "the agent regenerates it on approval" race where the thing you approved isn't the thing that ships. I work on the Nylas CLI, so the terminal commands below are the exact ones I reach for, and I'll pair every one with the raw curl so you can wire it into a backend in whatever language you like. This is deliberately not about escalating inbound threads to a human (that's a different problem, where the trigger is a message arriving). Here the trigger is the agent wanting to send , and the gate sits on the outbound path. Why a draft is the right approval primitive You could build approval a dozen ways. You could buffer the agent's output in a queue table and call send later. You could stash a JSON blob in Redis. Both work, and both quietly reinvent something the email stack already gives you. A draft is a real, persisted email object , on the mailbox, with a stable id . That buys you three things a homegr
This is a condensed version of my preprint ( DOI: 10.5281/zenodo.21345310 , CC BY 4.0). Reference implementation: askbar.pro . The library problem For thirty years the website has been a library: a visitor arrives with one question and is expected to find the answer themselves, navigating menus, pages, and filters. Visitors read a small fraction of site content. Most leave without doing the thing the site owner hoped for. Chat widgets bolted onto such sites change nothing: the maze remains, the widget just answers questions about the maze. The pattern The Librarian Pattern inverts the relationship. The site does not present itself; it asks what you need and assembles the answer. The bar as the primary interface. One persistent input, text and hold-to-talk voice. It replaces navigation. Scene reassembly (generative UI). The center of the screen is not a page but a scene, composed per recognized intent. Transitions morph rather than reload. A guide with a plan. The conversational layer is a consultant with a goal ladder, asking one next question, never presenting menus of three options. Two button systems. Global suggestion chips above the bar are visually separated from in-scene action cards. This prevents the "six buttons" degeneration of chat UIs. The static shadow. Every live scene has a server-rendered twin page: full text in the DOM, question-shaped headings, FAQ schema, llms.txt, freshness stamps. Humans get the agent; crawlers and AI answer engines get complete, citable pages, generated from the same content source. Structural GEO-readiness. Content already organized as questions and answers matches how generative engines retrieve and cite, by construction. The result that surprised me 24 hours after the discoverability layer went public, Yandex Alice (the largest Russian AI answer engine) began citing the reference implementation as its prime example for the "next-generation website" query, describing the mechanics correctly and distinguishing it from "a chat
Siri has been on the Apple Watch since day one, though I'm usually hard-pressed to find people who actually make good use of it. It's kind of just… been there - mostly as a way to set timers when my hands are full. But after playing around with the watchOS 27 developer beta, I get […]
iOS 27 escaped the developer world today with the launch of the first public beta. I've been testing the new operating system since early June, looking for quirks and seeing if it can live up to the hype Apple promised in the keynote. This year's iOS upgrades are what one might call a Snow Leopard […]
VistralNova began by developing Web3 gaming experiences and is now expanding toward developer...
There's a separate $1,750 rebate for used EVs, but both rebates have a price cap.
How I Built CodeGraph: A Living Knowledge Graph That Tells You What Breaks Before You Break It Built for HACKHAZARDS '26 — powered by Neo4j AuraDB, tree-sitter, Groq LLaMA, and Next.js The Problem That Frustrated Me Every developer knows this feeling. You join a new codebase. There are 50,000 lines of code. Your manager says "just fix this small bug in the authentication module." You make the change. You push. And suddenly three completely unrelated features are broken — a payment flow, a notification system, and a dashboard widget you've never even looked at. You spend the next four hours tracing function calls manually, reading code you've never seen, trying to understand why changing one function in auth.py broke something in notifications.py on the other side of the codebase. This is not a rare experience. According to JetBrains' developer survey, engineers spend 58% of their time reading and understanding code — not writing it. One wrong change in a large codebase can cost hours of debugging, failed deployments, and frustrated users. I built CodeGraph to solve this. Not with another AI chatbot that guesses at your code. With a real, queryable knowledge graph that actually understands how your codebase is connected. What CodeGraph Does CodeGraph takes any public GitHub repository URL and within seconds: Parses every function in the codebase using tree-sitter Maps every call relationship between functions as a directed graph Stores everything in Neo4j AuraDB as a live knowledge graph Lets you ask questions in plain English — answered by AI grounded in real graph data The result: paste a GitHub URL, see your entire codebase as an interactive graph, click any function, and instantly know what breaks if you change it. The Tech Stack Here's what I used and why each choice mattered: Backend: Python + FastAPI (REST API server) Neo4j AuraDB (graph database — the core of everything) tree-sitter (AST parser for Python, JS, TS, TSX) Groq API with LLaMA 3.3 70B (free-tier L
Welcome back to The Everyday Backend Engineer: Practical Design Patterns . In our last post, we made our core algorithms interchangeable using the Strategy Pattern. Today, we close out our design patterns roadmap with arguably the most native pattern in the entire Node.js ecosystem: The Observer Pattern . Let’s look at how to master event-driven decoupling to trigger secondary workflows seamlessly without bloat. 🔴 The Problem: Direct Inline Side-Effects Imagine you are writing a video processing engine or a simple order fulfillment system. When a specific event happens—such as an order being finalized—multiple unrelated departments want a piece of the action: The Notification Service needs to send an SMS and Email receipt. The Logistics Service needs to generate a warehouse fulfillment ticket. The Analytics Service needs to update marketing tracking boards. If you don't decouple these events, your primary execution service ends up managing a giant web of secondary micro-services: // ❌ Bad Practice: The primary service is drowning in secondary dependencies const EmailService = require ( ' ../services/email ' ); const WarehouseService = require ( ' ../services/warehouse ' ); const AnalyticsTracker = require ( ' ../services/analytics ' ); class OrderProcessor { async finalizeOrder ( order ) { console . log ( " Saving primary order to the database... " ); // Core business logic ends here // The codebase smell: Procedural cascading dependencies await EmailService . sendReceipt ( order . userEmail ); await WarehouseService . createShipment ( order . id ); await AnalyticsTracker . trackSale ( order . totalAmount ); } } module . exports = OrderProcessor ; Why does this slow your system down? Your core OrderProcessor is now structurally dependent on three separate systems. If the AnalyticsTracker throws a network timeout error or if the warehouse API changes its interface, your core transaction fails or hangs. Furthermore, adding a fourth side-effect (like an auditing logger
The failures that cost me the most in three years of self-hosting were never the ones that threw an error. An error is a gift: it tells you where to look. The expensive ones are the failures that report success while being broken . A page that returns 200 OK . A healthcheck that says the container is fine. A backup that exits cleanly. A command that prints nothing wrong. Everything green, everything lying. Here are four of them, all from the same box (a 2016 desktop, i7-6700 / 32 GB, Docker behind Caddy, reachable only over Tailscale). Each fails by handing you a success signal. Each cost me an evening the first time. The fixes are boring once you know them, the point is knowing the failure exists. Sanitized skeleton with all the config at the end. 1. A loading page that returns 200 This one I could find nothing written about, so it cost me the most. To keep the box quiet, I run the heavy services on-demand: Sablier stops idle containers and starts them on the first request. Caddy (with the Sablier plugin) gates a virtual host behind a container group, serves a "please wait, starting up" page while the group boots, then proxies through: myhost . my - tailnet . ts . net : 8081 { route { sablier http :// sablier : 10000 { group office session_duration 30 m } reverse_proxy nextcloud : 80 } } I gate my whole Nextcloud vhost, WebDAV included, this way. And here is the silent failure: if the gated group is not healthy, Sablier serves that HTML loading page for every request, and it serves it with 200 OK . A browser shows a spinner, fine. But my Obsidian vault syncs over WebDAV, and a WebDAV client asking for a directory listing got a 200 with a chunk of HTML instead of the XML it expected. Sync died with a cryptic no root multistatus found . Nextcloud itself was up and perfectly healthy the whole time. Every uptime check I had was green, because the gate in front kept answering 200 . The structural lesson: the moment you put a service on-demand behind a reverse proxy, tha
TL;DR Some things can't be checked with a number, like whether an animation feels right. So a second, read-only agent grades the first one against a written rubric it is not allowed to edit. In my run the reviewer rejected the builder three times, and the most interesting problem it caught was in the test evidence, not the code. In Part 1 I built a loop that chased a number, frames per second. But most of what we care about in software is not a number. "Does this region switch feel good?" has no assert. You cannot write expect(feelsRight).toBe(true) . So this part is about how you check quality when there is nothing to measure. The approach I used is a second agent that grades the first one against a written rubric. In my run the reviewer turned the builder down three times before it approved anything, and the most interesting problem it found was not in the code at all. A quick reminder of the definition, since this is Part 2 of 3: a loop is an external script that runs the agent, a separate check the agent cannot edit decides pass or fail, and it repeats until it passes or hits a limit. In Part 1 the check was a Playwright test. Here the check is another agent. The problem this loop solves In the browser you can switch regions, say from Tamil to Korean, which swaps out hundreds of posters at once. Done badly, the grid flashes blank and jumps around. Done well, it fades from one set to the next, keeps its layout, shows a loading state, and puts you back at the top. "Done well" is subjective, which is the kind of thing you cannot unit-test. So I wrote it down as a rubric and had a second agent apply it. The bar: a rubric a person owns The rubric is seven plain-English checks in a file, and the first line is the one that matters: Overall APPROVED requires every item PASS. This file is human-owned. Only a person changes the bar. The seven items are things like a crossfade instead of a flash, no layout shift, a visible loading state, posters that stay 2:3, and landing
TL;DR This loop runs on a schedule and succeeds by doing nothing almost every night. The pass/fail check is plain deterministic code, with no AI in the decision. It can run entirely free on your own machine. Only the cloud/CI version needs a paid API key. Plus the one bug that broke all three loops. The first two loops in this series work the same way from your side: you start them and watch. This last one runs on a schedule, like a nightly job, while you are not looking. That changes what success even means. A scheduled maintenance loop is doing its job when it does nothing. It should run every night, find nothing wrong, cost almost nothing, and still be there on the night something actually breaks. This part covers that loop, the hook mechanism that the whole series relies on, and a bug that broke all three loops in the least convenient place possible. The definition one more time, since this is Part 3 of 3: a loop is a trigger that runs the agent, a check the agent cannot edit that decides pass or fail, and a repeat, or here a wait until the next run. The only new thing this time is the trigger. A timer starts it instead of you. The problem this loop solves The browser's poster data is baked ahead of time into JSON files and images. In a real deployment that data goes stale as films are added and metadata changes, so you want to regenerate it every so often and confirm it is still valid before it ships: on a timer -> regenerate the data -> validate it -> green ships, red shouts The gate: a plain check with no model in it The check is a Node script. For every region file it confirms three things and exits non-zero if any of them fail: it matches the expected JSON schema, it has at least the minimum film count, and every poster file it points to actually exists on disk. There is no language model in that list. The regeneration step might use Claude, but the decision about whether the data is good is plain, deterministic code. That is on purpose. You do not want the
Why build something? And what if nobody ends up using it? There are good answers to the first one. You build because you need a thing that doesn't exist yet. You build to see if you can, the technical challenge, the "is this even possible?" You build to impress someone, or just because you think it'll make people's day a little less annoying. All of those are real reasons, and at different points, I told myself most of them. Then, a few days ago, late in the day, at the end of a coding session, five months into the project, I asked myself those two questions back-to-back. And for the first time, I couldn't answer the second one. Zeri worked. Every feature did what it was supposed to do. Both processes handshake cleanly, a variable set in one context showing up in another a second later, the TUI rendering exactly as I'd pictured it. And I sat there and couldn't come up with one honest sentence explaining why anyone would actually download it. That gap, between something built well and something that has a reason to exist, turned out to be the most useful thing this whole project taught me. So I'm shipping it anyway, and I'll tell you why. What I built Zeri is a TUI multi-language REPL. You launch it, pick a language, Python , JavaScript (with Bun ), Ruby , or LuaJIT , and you get an interactive session in your terminal. You can switch languages mid-session, share variables across them, save and reload your work, manage snippets, and talk to a local LLM through a command running on Ollama . The feature list isn't the interesting part, though. The interesting part is what's underneath. Two processes, one app Zeri is split into two processes: a headless engine written in C++23 and a TUI frontend built in Go using Bubble Tea and Lip Gloss . The engine does all the evaluation, state, and runtime coordination. The frontend does rendering, input, and everything the user actually sees and touches. They talk to each other over a custom binary IPC protocol that I built from sc
🎧 DJ ROOTS – Building a Real-Time Collaborative Music Platform with Gesture Control Crowd Vibes. You Control. Music is one of the best ways to bring people together. However, during parties, college events, hostel gatherings, or study sessions, one common problem always exists— who gets to control the music? Usually, one person owns the playlist while everyone else keeps requesting songs. This often creates confusion, interruptions, and arguments over what should play next. Our team wanted to solve this problem by creating a platform where everyone in the room gets an equal voice. Welcome to DJ ROOTS . 🚨 The Problem Traditional music streaming at group events has several limitations: Only one person controls the playlist. Song requests are ignored or forgotten. No real-time collaboration. Existing queue systems don't truly represent the crowd's choice. There is no simple browser-based solution that works instantly without downloading an app. We wanted to build something that makes music democratic . 💡 Our Solution DJ ROOTS is a real-time collaborative DJ platform where anyone can join a room using a simple room code. Participants can: Create or join a music room Add songs using YouTube Upvote or downvote tracks Automatically reorder the queue based on crowd votes Watch every change happen instantly across all connected devices Let the host control playback using webcam hand gestures Instead of one person deciding the playlist, the entire crowd decides what plays next. 🛠 Tech Stack Frontend React 19 Vite Tailwind CSS v4 Framer Motion Three.js GSAP OGL Backend Node.js Express.js Database & Authentication Supabase PostgreSQL Supabase Authentication Supabase Realtime Computer Vision Google MediaPipe Gesture Recognizer Audio Pipeline yt-dlp youtube-dl-exec HTML5 Audio API Web Audio API Deployment Vercel (Frontend) ⚙️ How It Works Users create or join a room using a unique room code. Songs are added using a YouTube link or search. Song metadata is automatically fetched. E
A Tesla representative at a DC hearing said the vehicle is “an active product being built.” But its timeline isn’t clear.
The creator of TV Time is building a successor app that will let users import their watch histories and preserve the community that formed around discussing their favorite shows.
DoorDash details the architecture behind Ask DoorDash, its AI-powered conversational shopping assistant, combining LLMs, specialized AI agents, MCP-based tooling, and an intelligence layer with persistent consumer memory and live backend data. Early results show up to 24% higher checkout conversion, 17% larger baskets, and improved intent accuracy using memory-backed sessions. By Leela Kumili