AI News Archive: July 22, 2026 — Part 10
Sourced from 500+ daily AI sources, scored by relevance.
- CEO Interview: OrangeAI
Will Kastroll, CEO of Orange AI, tells CB Insights how they view the market, customer needs, and their company. How do you define your market and where does your company fit into that space? There are over 39,000 independent agencies … The post CEO Interview: OrangeAI appeared first on CB Insights Research .
- These D-FW jobs have the most AI exposure. How does your profession stack up?
These D-FW jobs have the most AI exposure. How does your profession stack up? Dallas News
- New Industry Report Highlights the Growing Importance of AI Search Optimization for Korean Businesses
New Industry Report Highlights the Growing Importance of AI Search Optimization for Korean Businesses USA Today
- Startup Spotlight: MediaPact wants to reinvent digital ads for the AI era
As AI reshapes online search and advertising, Seattle startup MediaPact is building a marketplace to help brands and publishers strike direct sponsorship deals. Founder Lacie Thompson discusses launching the company, using AI to build without coding experience, and spotting a new opportunity in a rapidly changing digital media landscape. Read More
Score: 32🌐 MovesJul 22, 2026https://www.geekwire.com/2026/startup-spotlight-mediapact-wants-to-reinvent-digital-ads-for-the-ai-era/ - Every LangGraph Pattern You’ll Actually Use : Explained Properly
Prompt chains, routers, and full agents, walked through line by line with one reusable template If you’ve looked at LangGraph code before and felt lost in a pile of StateGraph, add_node, and add_edge calls, this guide is for you. We're going to slow down and actually explain what's happening at each step, not just show code and assume it's obvious. By the end, you’ll understand six ways to structure an LLM-powered system, when to reach for each one, and how to read (or write) the code without guessing. This article is adapted from the reference material: Workflow And Agents Why this matters before we touch any code A single call to an LLM is just a question and an answer. You send a prompt, you get text back, and that’s it. The model has no memory of what it should do next, no way to check its own work, and no ability to call a search engine or a calculator on its own. The moment you need more than one step (write a draft, then check it, then fix it), you need something to hold the pieces together: what happened so far, what should happen next, and how to move from one step to the other. That “something” is what this whole guide is about. There are two broad ways to build that structure. Anthropic’s own engineering team wrote a good explainer on this, and it’s worth reading directly: Building Effective Agents . Workflows vs. agents: the actual difference People throw these two words around interchangeably, which causes a lot of confusion. Here’s the distinction that matters: A workflow is a fixed path you designed in advance. You, the developer, decide: step one happens, then step two, maybe with a branch depending on a condition, then step three. The LLM fills in the content at each step, but it doesn’t get to change the route. Think of it like a recipe: the steps are printed on the card, and the cook (the LLM) follows them in order. An agent doesn’t have a fixed path. Instead, it’s given a goal, a set of tools, and the freedom to decide what to do next based on what just happened. It might call a tool, look at the result, decide it needs another tool, call that, and keep going until it thinks the job is done. Nobody wrote down the exact sequence of steps ahead of time. The model works that out as it goes. Neither one is “better.” Workflows are predictable, easier to test, and cheaper to run, because you know exactly what will happen. Agents are more flexible and can handle problems you didn’t fully anticipate, but that flexibility comes at the cost of predictability. An agent can wander, loop unnecessarily, or make a bad call that a fixed workflow would never have allowed in the first place. A rough rule of thumb: if you can draw the flowchart before you write any code, build a workflow. If you can’t, because the right next step genuinely depends on things you can’t predict, you probably need an agent. Do you actually need LangGraph? Short answer: no, not technically. Every pattern in this guide could be written as plain Python: a few functions and some if/else logic. LangGraph doesn’t add new capabilities that Python doesn’t already have. What it adds is infrastructure you’d otherwise have to build yourself, and would probably build badly the first few times: Persistence : saving the state of a conversation or task so it survives a restart, and letting a human pause the process to approve or reject a step before it continues. Streaming : showing partial output as it’s generated, from any point in your workflow, instead of making the user stare at a blank screen until everything finishes. Deployment tooling : ways to test, inspect, and debug what actually happened inside a run, which matters a lot once something goes wrong in production and you need to know why. If you’re just experimenting with a single prompt, skip LangGraph entirely. Once you’re chaining multiple steps together and need to keep track of what happened, it starts pulling its weight. The template we’ll use for every example Every code example below follows the same seven-part layout. Learn this once, and you can read any of the patterns further down without re-learning how the code is organized each time. Imports : what we’re pulling in and why State : the shared data structure every node reads from and writes to Tools (only when the pattern uses them) : functions the LLM can choose to call Nodes : the individual steps in the graph, each one usually a single Python function Edges : the wiring that decides which node runs after which Assembly : where we actually build the graph object and compile it Entrypoint : the code that runs the finished graph with real input Keeping this order consistent is the whole point. Once “State” always means the same thing and “Edges” always means the same thing, you stop having to reverse-engineer someone else’s code structure every time you open a new file. Building block: the “augmented” LLM Before any of the six patterns, you need one core idea: a plain LLM and an LLM that’s been given extra capabilities are not the same thing, and LangChain calls the upgraded version an “augmented” LLM. On its own, an LLM just turns text into more text. Two upgrades change what it can do: Structured output forces the model to answer in a specific shape, a Python object with named fields, instead of free-form prose you’d have to parse yourself. You describe the shape you want using a Pydantic model (a class that defines field names, types, and short descriptions), and the LLM fills it in. Tool binding gives the model a menu of functions it’s allowed to call. The LLM doesn’t actually run the function. It decides whether a function is needed and what arguments to pass, and your code is the one that actually executes it and hands the result back. from langchain_anthropic import ChatAnthropic # This is just a plain, unmodified LLM connection. llm = ChatAnthropic(model="claude-3-5-sonnet-latest") Here’s structured output in practice: from pydantic import BaseModel, Field # This class describes the exact shape we want the LLM's answer to take. # Two fields: the search query itself, and a short justification for it. class SearchQuery(BaseModel): search_query: str = Field(description="A web-search-optimized version of the question.") justification: str = Field(description="Why this query answers the user's request.") # .with_structured_output() wraps the LLM so it always replies in this shape. structured_llm = llm.with_structured_output(SearchQuery) output = structured_llm.invoke("How does a calcium CT score relate to cholesterol?") print(output.search_query) # a clean, searchable string print(output.justification) # the model's reasoning for picking that query Without with_structured_output, you'd get back a paragraph of text and have to write regex or string-parsing logic to pull the query out of it. That's fragile: the model might phrase things slightly differently every time. Structured output sidesteps the problem entirely by making the shape non-negotiable. And here’s tool binding: def multiply(a: int, b: int) -> int: return a * b # bind_tools tells the LLM this function exists and describes what it does, # based on the function's name, type hints, and docstring. llm_with_tools = llm.bind_tools([multiply]) msg = llm_with_tools.invoke("What is 2 times 3?") # The LLM doesn't compute 2*3 itself. It recognizes multiply() fits this task # and returns a *request* to call it, with the arguments filled in. msg.tool_calls # -> [{'name': 'multiply', 'args': {'a': 2, 'b': 3}, 'id': '...'}] Notice the model never actually multiplies anything. It just says “call multiply with a=2, b=3." Your code has to be the one that runs it. We'll see exactly how in the full agent example near the end. With those two ideas in hand, we can move through the six patterns, from simplest to most autonomous. Pattern 1: Prompt Chaining The idea: break one big task into several smaller LLM calls that run one after another, where each step builds on the output of the one before it. Use this when a task naturally breaks into stages, and getting each stage right on its own is easier than trying to get the whole thing right in a single shot. A good comparison is editing an essay: you write a rough draft, then you tighten the language, then you do a final polish pass. Each pass has a narrow job, and narrow jobs are easier for an LLM (and for a human) to do well than “write a perfect essay in one attempt.” Our example: write a joke, improve it with wordplay, then add a twist ending. There’s also a quality check in the middle: if the first draft doesn’t look like a real joke, we stop early instead of wasting two more LLM calls polishing something broken. # ============================================================ # MODULE 1: IMPORTS # ============================================================ from typing_extensions import TypedDict from langgraph.graph import StateGraph, START, END # ============================================================ # MODULE 2: STATE # ============================================================ # State is just a dictionary with a known shape. Every node function # receives the current state and returns a partial update to it. # LangGraph merges that update back into the shared state automatically. class State(TypedDict): topic: str joke: str improved_joke: str final_joke: str # ============================================================ # MODULE 3: TOOLS # ============================================================ # No tools in this pattern. Every step is a plain LLM call. # ============================================================ # MODULE 4: NODES # ============================================================ def generate_joke(state: State): """Step 1: write a first-draft joke about the topic.""" msg = llm.invoke(f"Write a short joke about {state['topic']}") return {"joke": msg.content} def improve_joke(state: State): """Step 2: take that draft and add wordplay to it.""" msg = llm.invoke(f"Make this joke funnier by adding wordplay: {state['joke']}") return {"improved_joke": msg.content} def polish_joke(state: State): """Step 3: give it a final twist ending.""" msg = llm.invoke(f"Add a surprising twist to this joke: {state['improved_joke']}") return {"final_joke": msg.content} def check_punchline(state: State): """ This isn't a node that generates anything. It's a gate function used by a conditional edge. It looks at the draft joke and decides whether it's worth continuing, based on a rough heuristic: does it contain a '?' or '!'? If not, we treat it as a failed first draft and stop rather than polishing something broken. """ if "?" in state["joke"] or "!" in state["joke"]: return "Pass" return "Fail" # ============================================================ # MODULE 5: EDGES # ============================================================ workflow = StateGraph(State) workflow.add_node("generate_joke", generate_joke) workflow.add_node("improve_joke", improve_joke) workflow.add_node("polish_joke", polish_joke) workflow.add_edge(START, "generate_joke") # add_conditional_edges routes to a *different* next node depending on # what the gate function returns. Here: "Pass" continues the chain, # "Fail" jumps straight to the end. workflow.add_conditional_edges( "generate_joke", check_punchline, {"Pass": "improve_joke", "Fail": END}, ) workflow.add_edge("improve_joke", "polish_joke") workflow.add_edge("polish_joke", END) # ============================================================ # MODULE 6: ASSEMBLY # ============================================================ chain = workflow.compile() # ============================================================ # MODULE 7: ENTRYPOINT # ============================================================ if __name__ == "__main__": state = chain.invoke({"topic": "cats"}) print("Initial joke:", state["joke"]) if "improved_joke" in state: print("Improved joke:", state["improved_joke"]) print("Final joke:", state["final_joke"]) else: print("Joke failed the quality gate: no punchline detected.") A few things worth slowing down on: Nodes only return what changed. generate_joke returns {"joke": msg.content}, not the entire state object. LangGraph takes that small dictionary and merges it into the existing state for you. The gate function doesn’t touch state at all. It just reads it and returns a string (“Pass” or “Fail”), and that string is what add_conditional_edges uses to pick the next node. START and END are LangGraph's built-in markers for "the graph begins here" and "the graph is finished." Every graph needs both. Pattern 2: Parallelization The idea: when the sub-tasks don’t depend on each other, run them at the same time instead of one after another. If you’re generating a joke, a story, and a poem about the same topic, there’s no reason the poem has to wait for the joke to finish first. Nothing in the poem depends on the joke. This is also useful when you want several independent “opinions” on the same input, for example, asking three different prompts to search for the same information from different angles, then combining what they each found. # ============================================================ # MODULE 1: IMPORTS # ============================================================ from typing_extensions import TypedDict from langgraph.graph import StateGraph, START, END # ============================================================ # MODULE 2: STATE # ============================================================ class State(TypedDict): topic: str joke: str story: str poem: str combined_output: str # ============================================================ # MODULE 3: TOOLS # ============================================================ # None needed here either. # ============================================================ # MODULE 4: NODES # ============================================================ def call_llm_1(state: State): """Generate a joke about the topic.""" msg = llm.invoke(f"Write a joke about {state['topic']}") return {"joke": msg.content} def call_llm_2(state: State): """Generate a short story about the topic.""" msg = llm.invoke(f"Write a story about {state['topic']}") return {"story": msg.content} def call_llm_3(state: State): """Generate a poem about the topic.""" msg = llm.invoke(f"Write a poem about {state['topic']}") return {"poem": msg.content} def aggregator(state: State): """ This node doesn't call the LLM at all. Its only job is to wait for all three branches to finish, then stitch their outputs together into one combined string. """ combined = f"Here's a story, joke, and poem about {state['topic']}!\n\n" combined += f"STORY:\n{state['story']}\n\n" combined += f"JOKE:\n{state['joke']}\n\n" combined += f"POEM:\n{state['poem']}" return {"combined_output": combined} # ============================================================ # MODULE 5: EDGES # ============================================================ parallel_builder = StateGraph(State) parallel_builder.add_node("call_llm_1", call_llm_1) parallel_builder.add_node("call_llm_2", call_llm_2) parallel_builder.add_node("call_llm_3", call_llm_3) parallel_builder.add_node("aggregator", aggregator) # All three branches start directly from START. That's what makes # them run in parallel instead of one after another. Then all three # feed into the same aggregator node, which waits until every branch # has completed before it runs. parallel_builder.add_edge(START, "call_llm_1") parallel_builder.add_edge(START, "call_llm_2") parallel_builder.add_edge(START, "call_llm_3") parallel_builder.add_edge("call_llm_1", "aggregator") parallel_builder.add_edge("call_llm_2", "aggregator") parallel_builder.add_edge("call_llm_3", "aggregator") parallel_builder.add_edge("aggregator", END) # ============================================================ # MODULE 6: ASSEMBLY # ============================================================ parallel_workflow = parallel_builder.compile() # ============================================================ # MODULE 7: ENTRYPOINT # ============================================================ if __name__ == "__main__": state = parallel_workflow.invoke({"topic": "cats"}) print(state["combined_output"]) The key structural difference from prompt chaining: three separate edges leave START, instead of one edge chaining into the next. LangGraph sees that call_llm_1, call_llm_2, and call_llm_3 don't depend on each other's output, so it can run them concurrently and simply wait for all three before moving on to aggregator. Pattern 3: Routing The idea: look at the input first, classify what kind of request it is, and send it down a different path depending on the answer. This is useful whenever different types of input genuinely need different handling. A customer support message about billing shouldn’t go through the same logic as a technical bug report. The trick is that the “router” itself is just another LLM call, one that uses structured output to guarantee it returns one of a fixed set of labels, rather than a free-text guess you’d have to interpret. # ============================================================ # MODULE 1: IMPORTS # ============================================================ from typing_extensions import TypedDict, Literal from pydantic import BaseModel, Field from langchain_core.messages import HumanMessage, SystemMessage from langgraph.graph import StateGraph, START, END # ============================================================ # MODULE 2: STATE # ============================================================ class State(TypedDict): input: str decision: str output: str # ============================================================ # MODULE 3: TOOLS # ============================================================ # Not a callable tool, but the same idea: a schema that constrains # what the router is allowed to say. Literal[...] means the model # can ONLY answer with one of these three exact strings. class Route(BaseModel): step: Literal["poem", "story", "joke"] = Field( description="The next step in the routing process." ) router = llm.with_structured_output(Route) # ============================================================ # MODULE 4: NODES # ============================================================ def llm_call_1(state: State): """Handle requests classified as 'story'.""" result = llm.invoke(state["input"]) return {"output": result.content} def llm_call_2(state: State): """Handle requests classified as 'joke'.""" result = llm.invoke(state["input"]) return {"output": result.content} def llm_call_3(state: State): """Handle requests classified as 'poem'.""" result = llm.invoke(state["input"]) return {"output": result.content} def llm_call_router(state: State): """ Classify the user's input into one of three buckets, using the Route schema above so the answer is guaranteed to be exactly "story", "joke", or "poem", never something unexpected like "Story!" or "I think it's a joke." """ decision = router.invoke([ SystemMessage(content="Route the input to story, joke, or poem based on the user's request."), HumanMessage(content=state["input"]), ]) return {"decision": decision.step} def route_decision(state: State): """ Gate function for the conditional edge. Reads the classification made above and returns the name of the node that should handle it. """ if state["decision"] == "story": return "llm_call_1" elif state["decision"] == "joke": return "llm_call_2" elif state["decision"] == "poem": return "llm_call_3" # ============================================================ # MODULE 5: EDGES # ============================================================ router_builder = StateGraph(State) router_builder.add_node("llm_call_1", llm_call_1) router_builder.add_node("llm_call_2", llm_call_2) router_builder.add_node("llm_call_3", llm_call_3) router_builder.add_node("llm_call_router", llm_call_router) router_builder.add_edge(START, "llm_call_router") router_builder.add_conditional_edges( "llm_call_router", route_decision, { "llm_call_1": "llm_call_1", "llm_call_2": "llm_call_2", "llm_call_3": "llm_call_3", }, ) router_builder.add_edge("llm_call_1", END) router_builder.add_edge("llm_call_2", END) router_builder.add_edge("llm_call_3", END) # ============================================================ # MODULE 6: ASSEMBLY # ============================================================ router_workflow = router_builder.compile() # ============================================================ # MODULE 7: ENTRYPOINT # ============================================================ if __name__ == "__main__": state = router_workflow.invoke({"input": "Write me a joke about cats"}) print(state["output"]) Notice llm_call_1, llm_call_2, and llm_call_3 are nearly identical here. In a real project, they'd usually differ by using different system prompts, different tools, or even entirely different models suited to each type of task. The point of routing isn't the destination nodes; it's that the router reliably sends each input to the right specialist. Pattern 4: Orchestrator-Worker The idea: one LLM call plans out an unknown number of sub-tasks, then a worker handles each one (in parallel) and a final step stitches all the results together. The key difference from plain parallelization is that you don’t know ahead of time how many parallel branches you’ll need. In Pattern 2, we hardcoded exactly three branches (joke, story, poem). Here, the number of branches is decided at runtime by the orchestrator itself. A good real-world case: writing a report. You don’t know in advance how many sections the report needs. That depends on the topic. So you let an LLM plan the sections first, and only then do you know how many workers to spin up. This needs two new pieces of machinery: Send : lets one node dynamically create multiple parallel branches at runtime, one per item in a list, instead of you hardcoding a fixed number of edges. operator.add as a reducer: when multiple workers all write to the same state key at the same time, LangGraph needs to know how to combine their results instead of one overwriting another. operator.add tells it: just concatenate the lists together. # ============================================================ # MODULE 1: IMPORTS # ============================================================ import operator from typing import Annotated, List from typing_extensions import TypedDict from pydantic import BaseModel, Field from langchain_core.messages import HumanMessage, SystemMessage from langgraph.graph import StateGraph, START, END from langgraph.constants import Send # ============================================================ # MODULE 2: STATE # ============================================================ class Section(BaseModel): name: str = Field(description="Name for this section of the report.") description: str = Field(description="What this section should cover.") class Sections(BaseModel): sections: List[Section] = Field(description="All sections of the report.") # The main graph state. class State(TypedDict): topic: str sections: list[Section] # Annotated[list, operator.add] is the important part here: it tells # LangGraph that when multiple workers write to "completed_sections" # at the same time, it should APPEND their results together rather # than one worker's write erasing another's. completed_sections: Annotated[list, operator.add] final_report: str # A separate, smaller state just for what an individual worker needs. # It only has to know about the one section it's writing. class WorkerState(TypedDict): section: Section completed_sections: Annotated[list, operator.add] # ============================================================ # MODULE 3: TOOLS # ============================================================ planner = llm.with_structured_output(Sections) # ============================================================ # MODULE 4: NODES # ============================================================ def orchestrator(state: State): """Ask the LLM to plan out how many sections the report needs, and what each covers.""" report_sections = planner.invoke([ SystemMessage(content="Generate a plan for the report."), HumanMessage(content=f"Here is the report topic: {state['topic']}"), ]) return {"sections": report_sections.sections} def llm_call(state: WorkerState): """A single worker: writes the content for exactly one section.""" section = llm.invoke([ SystemMessage(content="Write a report section."), HumanMessage(content=f"Section name: {state['section'].name}\nDescription: {state['section'].description}"), ]) # Wrapped in a list because operator.add expects to concatenate lists. return {"completed_sections": [section.content]} def synthesizer(state: State): """Once every worker has finished, join all the sections into one document.""" completed_report_sections = "\n\n---\n\n".join(state["completed_sections"]) return {"final_report": completed_report_sections} def assign_workers(state: State): """ This is what makes the dynamic fan-out possible. Send(node_name, payload) schedules one run of "llm_call" per section the orchestrator planned. If the plan has 3 sections, this creates 3 parallel workers; if it has 7, it creates 7. We never had to know that number in advance. """ return [Send("llm_call", {"section": s}) for s in state["sections"]] # ============================================================ # MODULE 5: EDGES # ============================================================ orchestrator_worker_builder = StateGraph(State) orchestrator_worker_builder.add_node("orchestrator", orchestrator) orchestrator_worker_builder.add_node("llm_call", llm_call) orchestrator_worker_builder.add_node("synthesizer", synthesizer) orchestrator_worker_builder.add_edge(START, "orchestrator") # Instead of add_conditional_edges (which picks ONE next node), # we use add_conditional_edges with assign_workers, which can spawn # MANY next nodes at once via Send(). orchestrator_worker_builder.add_conditional_edges( "orchestrator", assign_workers, ["llm_call"] ) orchestrator_worker_builder.add_edge("llm_call", "synthesizer") orchestrator_worker_builder.add_edge("synthesizer", END) # ============================================================ # MODULE 6: ASSEMBLY # ============================================================ orchestrator_worker = orchestrator_worker_builder.compile() # ============================================================ # MODULE 7: ENTRYPOINT # ============================================================ if __name__ == "__main__": state = orchestrator_worker.invoke({"topic": "Create a report on LLM scaling laws"}) print(state["final_report"]) If you only remember one thing from this pattern, make it this: Send is for when the number of parallel branches isn't known until the graph is already running. Everything else about it (nodes, edges, state) works the same way as the patterns before it. Pattern 5: Evaluator-Optimizer The idea: one LLM generates something, a second LLM call grades it, and if it doesn’t pass, the feedback gets fed back into another generation attempt, looping until it’s good enough. This is essentially a built-in editor that won’t let a weak first draft through. This is worth reaching for whenever “good” is something you can actually check for: grading a joke as funny or not, checking a generated SQL query for syntax errors, or verifying a RAG answer is actually backed by the retrieved documents rather than invented. # ============================================================ # MODULE 1: IMPORTS # ============================================================ from typing_extensions import TypedDict, Literal from pydantic import BaseModel, Field from langgraph.graph import StateGraph, START, END # ============================================================ # MODULE 2: STATE # ============================================================ class State(TypedDict): joke: str topic: str feedback: str funny_or_not: str # ============================================================ # MODULE 3: TOOLS # ============================================================ class Feedback(BaseModel): grade: Literal["funny", "not funny"] = Field(description="Whether the joke is funny.") feedback: str = Field(description="If not funny, concrete advice on how to fix it.") evaluator = llm.with_structured_output(Feedback) # ============================================================ # MODULE 4: NODES # ============================================================ def llm_call_generator(state: State): """ Write a joke. If this is a retry (there's feedback in state from a previous failed attempt), pass that feedback back to the model so it actually improves rather than generating a fresh random attempt. """ if state.get("feedback"): msg = llm.invoke( f"Write a joke about {state['topic']} but take into account this feedback: {state['feedback']}" ) else: msg = llm.invoke(f"Write a joke about {state['topic']}") return {"joke": msg.content} def llm_call_evaluator(state: State): """Grade the joke and, if it fails, explain why.""" grade = evaluator.invoke(f"Grade the joke: {state['joke']}") return {"funny_or_not": grade.grade, "feedback": grade.feedback} def route_joke(state: State): """Gate function: accept and stop, or loop back with feedback.""" if state["funny_or_not"] == "funny": return "Accepted" return "Rejected + Feedback" # ============================================================ # MODULE 5: EDGES # ============================================================ optimizer_builder = StateGraph(State) optimizer_builder.add_node("llm_call_generator", llm_call_generator) optimizer_builder.add_node("llm_call_evaluator", llm_call_evaluator) optimizer_builder.add_edge(START, "llm_call_generator") optimizer_builder.add_edge("llm_call_generator", "llm_call_evaluator") # This is the loop: if the evaluator says "Rejected + Feedback", control # goes BACK to llm_call_generator instead of forward to END. That's what # turns this into an iterative refinement loop rather than a straight line. optimizer_builder.add_conditional_edges( "llm_call_evaluator", route_joke, {"Accepted": END, "Rejected + Feedback": "llm_call_generator"}, ) # ============================================================ # MODULE 6: ASSEMBLY # ============================================================ optimizer_workflow = optimizer_builder.compile() # ============================================================ # MODULE 7: ENTRYPOINT # ============================================================ if __name__ == "__main__": state = optimizer_workflow.invoke({"topic": "Cats"}) print(state["joke"]) One practical warning: nothing in this graph stops it from looping forever if the evaluator is a harsh grader and the generator can’t satisfy it. In real projects, you’d usually add a retry counter to State and force an exit after, say, three attempts. Otherwise, a stubborn evaluator can burn through your API budget without you noticing. Pattern 6: The Agent The idea: this is where we stop pre-drawing the flowchart. Instead of you deciding the sequence of steps, the LLM decides (on every turn) whether it needs to call a tool, and it keeps looping between “think” and “act” until it decides the job is done. This is genuinely different from every pattern above. In prompt chaining, routing, and the rest, you wrote down which node comes after which. Here, there’s really only one loop: the model thinks, optionally calls a tool, sees the result, and thinks again, and it can go around that loop as many times as it needs to. Use this when the task is open-ended enough that you can’t lay out the steps in advance, for instance, a multi-step calculation where you don’t know how many operations will be needed until you’re partway through it. # ============================================================ # MODULE 1: IMPORTS # ============================================================ from typing_extensions import Literal from langchain_core.tools import tool from langchain_core.messages import SystemMessage, ToolMessage, HumanMessage from langgraph.graph import StateGraph, START, END, MessagesState # ============================================================ # MODULE 2: STATE # ============================================================ # MessagesState is a ready-made state type from LangGraph that already # has one field, "messages," designed to hold a running list of chat # messages. We don't need to define our own State class this time # because a conversation history is exactly what this pattern needs. # ============================================================ # MODULE 3: TOOLS # ============================================================ # The @tool decorator turns a normal Python function into something # the LLM can request to call. The docstring matters. The model reads # it to decide when this tool is the right one to use. @tool def multiply(a: int, b: int) -> int: """Multiply a and b.""" return a * b @tool def add(a: int, b: int) -> int: """Add a and b.""" return a + b @tool def divide(a: int, b: int) -> float: """Divide a and b.""" return a / b tools = [add, multiply, divide] tools_by_name = {t.name: t for t in tools} llm_with_tools = llm.bind_tools(tools) # ============================================================ # MODULE 4: NODES # ============================================================ def llm_call(state: MessagesState): """ The "thinking" step. The model looks at the full conversation so far and decides: answer directly, or request a tool call. Either way, its response gets appended to the messages list. """ return { "messages": [ llm_with_tools.invoke( [SystemMessage(content="You are a helpful assistant tasked with performing arithmetic on a set of inputs.")] + state["messages"] ) ] } def tool_node(state: dict): """ The "acting" step. This is where a tool call the model requested actually gets executed. The LLM never runs code itself, it only asks for it. We look up the requested tool by name, run it with the arguments the model provided, and package the result as a ToolMessage so the model can read it on its next turn. """ result = [] for tool_call in state["messages"][-1].tool_calls: selected_tool = tools_by_name[tool_call["name"]] observation = selected_tool.invoke(tool_call["args"]) result.append(ToolMessage(content=observation, tool_call_id=tool_call["id"])) return {"messages": result} def should_continue(state: MessagesState) -> Literal["environment", END]: """ This is the heart of the agent loop. After the model thinks, we check: did it ask for a tool? If yes, go run the tool ("Action"). If not, meaning it gave a final answer instead, the loop ends. """ last_message = state["messages"][-1] if last_message.tool_calls: return "Action" return END # ============================================================ # MODULE 5: EDGES # ============================================================ agent_builder = StateGraph(MessagesState) agent_builder.add_node("llm_call", llm_call) agent_builder.add_node("environment", tool_node) agent_builder.add_edge(START, "llm_call") agent_builder.add_conditional_edges( "llm_call", should_continue, {"Action": "environment", END: END}, ) # This is the edge that makes it a loop rather than a straight line: # after a tool runs, control goes back to llm_call, not forward to END. # The model gets to see the tool's result and decide what to do next: # answer, or call another tool. agent_builder.add_edge("environment", "llm_call") # ============================================================ # MODULE 6: ASSEMBLY # ============================================================ agent = agent_builder.compile() # ============================================================ # MODULE 7: ENTRYPOINT # ============================================================ if __name__ == "__main__": messages = [HumanMessage(content="Add 3 and 4. Then take the output and multiply it by 4.")] result = agent.invoke({"messages": messages}) for m in result["messages"]: m.pretty_print() Walk through what actually happens on that input, step by step: llm_call runs. The model reads "add 3 and 4, then multiply by 4" and decides it needs the add tool first. It returns a tool call, not a final answer. should_continue checks the last message, sees a tool call, and returns "Action". tool_node runs add(3, 4), gets 7, and appends that result as a ToolMessage. Control loops back to llm_call. The model now sees "3 + 4 = 7" in its message history and decides the next step is multiply(7, 4). should_continue sees another tool call, routes to "Action" again. tool_node runs multiply(7, 4), gets 28. Control loops back to llm_call one more time. Now the model has everything it needs, so it responds with a final answer instead of another tool call. should_continue sees no tool calls this time and returns END. The loop stops. Nobody wrote “call add, then call multiply” anywhere in the code. The model figured that sequence out on its own, one decision at a time. That’s the entire difference between an agent and a workflow. Which pattern should you actually use? Start simple and add complexity only when you hit its limits: Just need to force a clean answer shape or let the model use one tool? You don’t need a graph at all. The augmented LLM alone is enough. Task breaks cleanly into ordered stages, each one easier alone than combined? Prompt chaining. Independent sub-tasks that don’t need each other’s output? Parallelization. Different input types genuinely need different handling? Routing. Don’t know how many sub-tasks you’ll need until you see the input? Orchestrator-worker. “Good” output is something you can actually check programmatically or with a second LLM call? Evaluator-optimizer. The right sequence of steps can’t be known ahead of time at all? That’s the only case where you actually need a full agent , and it’s worth trying every other pattern first, because a workflow you can predict is a workflow you can debug. Every LangGraph Pattern You’ll Actually Use : Explained Properly was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.
- Why Mark Cuban says many AI data centers could wind up as 'pickleball courts'
Why Mark Cuban says many AI data centers could wind up as 'pickleball courts' Business Insider
- The most useful ways to connect your apps to ChatGPT and Claude
This article is republished with permission from Wonder Tools , a newsletter that helps you discover the most useful sites and apps. I’ve changed how I use Claude and ChatGPT lately. They’ve become my digital dashboards, linked to many of the tools I rely on. I can ask Claude to add to my calendar, query my meeting notes, update me on my email, or find a passage I highlighted in my digital notebook. Claude Connectors and ChatGPT plugins connect to hundreds of services. These include Superhuman Mail for email, Google Calendar, Granola for meeting notes, and Readwise for my online highlights. Read on for how and why to link your favorite tools to your AI assistant, and examples of connections and queries I’ve found useful so far. Why Connecting Tools to Claude and ChatGPT Is So Useful Claude and ChatGPT know the context for my work because I’ve set up Projects for my primary work areas. Each has detailed instructions and reference documents. And the AI has a memory of the work I do, my style, my preferences, and my objectives. So I can ask my AI assistant to: Plan: Add four prep sessions to open morning slots on my calendar next week for the classes I’m teaching this fall. Include in each event description relevant excerpts from my meeting summary and reference the recent planning notes I dictated. Research: Gather recent links I’ve saved to Raindrop, my bookmarking tool, that might be relevant to my team’s research. Then create a new reminder with those links and a summary of my recent related notes. These multiple-part commands require context. They won’t work in Google Calendar, Raindrop, or Granola directly. That’s why it’s so helpful to have Claude or ChatGPT as the command center. MCP is the New USB These connectors have a technical name: MCP, or Model Context Protocol . But just as you don’t need to think about USB details when you plug in a printer, or http specifications when you use the Web, you can use MCP without understanding its technical details. All you need to know is that MCP is a way of linking software tools, sites, and apps to AI platforms like Claude and ChatGPT. Remember the world prior to USB? Printers, hard drives, cameras, and external monitors had their own special cords to connect to your computer. I just cleaned out dozens of them from a drawer in my Manhattan apartment. Now they’re obsolete because USB ports are everywhere. MCP is a similar unifying standard for linking tools to AI. 5 Ways I’m Using Tools Connected to Claude Manage Email I rely on Superhuman Mail to read, organize, and respond to email. It’s fast, easy to use, reliable, and integrates with my calendar. I use it with three distinct email addresses. Because I have to act on important messages, I’ve linked it to Claude. Get started: The connection guide walks you through linking your email to Claude or ChatGPT. You can then ask your AI assistant to: “Help me turn a bunch of starred emails into an afternoon plan.” “List important messages I’ve sent this month that the recipient hasn’t yet opened.” “Draft concise responses to routine customer questions for my review.” Some of these tactics will also work with Gmail and Outlook connectors. Example query: “ Look at my five most recent starred emails, suggest an action list for this afternoon based on my priority list, then put an hour on my Google Calendar to act on them.” Do More with Meeting Notes I use Granola as my notepad during meetings. It transcribes conversations, then creates a summary based on the transcript and my own notes. (See my guide ). I can already ask questions about my meetings in Granola without needing a separate AI tool. But the advantage of linking Granola with Claude (or ChatGPT) is that Claude has access to insights in my notes, email, and Google Drive, so it can integrate the info it pulls from Granola within the context of a broader analysis. Get started: The Granola MCP guide explains how to link it to your AI. Unlike many other paid services, Granola actually lets free users query meeting notes (for the past 30 days) using your AI tool of choice. Example query: “ Give me a summary of the research questions I said I’d follow up on in my meeting with Pat. Next to each task include a bulleted list of the background details I already collected in my research spreadsheet.” Edit Images and Videos Photoshop and Premiere are powerful but complicated. Now you can edit an image or video without even opening a separate app. Set up the plugin, then tell your AI assistant to use it in your prompt. The AI assistants are often clever enough to figure out which tool to use even if you don’t explicitly mention it. Get started: Install the Adobe app in ChatGPT. Or add it to Claude, using this guide . Your AI assistant will now have access to the capabilities of Photoshop, Premiere, Firefly, Express, Acrobat, and other Adobe apps. You don’t even need an Adobe account to get started, though it might be helpful to get a free one if you want to organize, improve, and act on your creations later. ( Canva’s MCP is also useful). Example query: “Help me change the text in this graphic.” Or “Reformat this horizontal video clip for YouTube Shorts or Instagram Reels.” Or “Add background blur to this headshot, fix the lighting, and crop it for a portrait.” As a test, I changed the first line in an illustration from “Bold” to “Kind.” Notice that the first attempt wasn’t perfect. The period after “Kind” was missing. But a quick edit request fixed that. The Photoshop edit preserved the font, style, spacing, and angle. The benefit: Instead of hunting through Photoshop menus trying to figure out how to do this, I just asked ChatGPT to use Photoshop to make a change. In the long run, being able to use natural language to accomplish tasks like this may shift how we spend our time away from technical menu-hopping toward more creative work. We’ll spend more time thinking about what to do and why, rather than how to technically get it done. Find Highlights I use Readwise to collect the passages I highlight when reading online or on my Kindle. It also hosts passages I save when listening to podcasts with the Snipd app. Get started: The Readwise MCP lets you make use of the highlights you’ve made while working on other projects with an AI assistant. Example query : “Show me a bunch of my Readwise highlights that include descriptions of desserts, especially from European novels, then gather a list of related recipes I can make with my daughters before our trip.” Research Legal Cases Court Listener from the Free Law Project is a handy way of gathering info about court cases. You can ask for records related to Elon Musk’s recent testimony without paying for a legal research service. Get started: Use the Court Listener MCP guide for free with Claude or ChatGPT. First set up a free Court Listener account. Example query: “Review the news article at XYZ link, find the case that’s being discussed, and give me additional details about the case and any other related recent cases.” Other Useful MCP Tools Substack has a new MCP , available to select publishers as of now. It lets Claude coach me on my analytics. I recently asked for an analysis of send times to figure out how they impact open and click rates. Substack’s help page notes that the MCP has “read-only access to publication data such as dashboard metrics, traffic data, and publication settings. It cannot publish posts, send Notes, or modify your account.” Rize is my favorite tool for time-tracking. I linked it to Claude so I can learn from how I’m spending my time and assess that alongside info from my meetings, email and calendar. The Rize MCP page includes use-cases and helped me get started. Rize requires a paid subscription. I use Raindrop to save links I’ll need later. I checked the Raindrop MCP page to set it up and learn about the kinds of queries I can run from Claude. When I’m doing research in a project, for instance, I can ask it to pull in relevant links I’ve saved. Or I can even ask Claude to put the links from a spreadsheet I’m working on into my Raindrop bookmark collection with appropriate tags. Sublime is another tool I use to save quotes, images and useful pages online. Unlike Raindrop and other well-designed clipping tools like MyMind , which are fully private, Sublime lets me see related material other people have saved. Now I can ask Claude to pull in relevant material from Sublime . How to Link Tools to Your AI Assistant Decide what kind of connector will be useful to you: Email: Gmail, Outlook, Superhuman, and other email services now let you analyze and respond to your messages. Files: Analyze or act on files in your Google Drive, Dropbox, Box, Slack, Notion, or anywhere else you keep your documents and files. Planning: Add events to your Google or Outlook calendar, or organize projects with tools like Airtable, Monday, ClickUp, Asana, and Linear. Fun: Create Spotify playlists based on your work vibe or search StubHub or SeatGeek for tickets your family or friends might enjoy. Pick from your AI tool’s curated list. Claude and ChatGPT each have a bunch of services pre-configured to work. Perplexity now does too. Popular ones include Google Drive, Gmail, Google Calendar, Canva, Figma, and Notion. Paste in the address of a custom connector. For tools that are not on the default list, you put in an MCP address, which is like a special website to connect an external service to your AI tool. Find more to try in a directory . Be Careful About Linking Private Data Think twice before connecting services that host sensitive info. I haven’t linked my bank accounts to my AI tools, for example. If you do that and someone gets access to your AI account, they’ll be able to find out a lot about your finances. It can happen when a thief uses a “prompt injection” to manipulate an AI tool into releasing sensitive info. Or it can happen if your phone is lost or stolen. New York, London, Paris, and other major cities see thousands of phones stolen each year. Data can also leak from AI systems. It’s rare, but there have been cases like this one . Be Cautious About Letting AI Tools Act on Your Behalf I’m not yet letting AI tools send emails for me. Or submit forms or applications. If Claude or ChatGPT generates something odd because of a glitch, or because I rushed a query, I want to be the one noticing the error. When you start connecting AI tools to external services, you have the option to give your AI assistant power to do things on your behalf. That can be useful for research, summarizing meeting notes, or cleaning up messy computer folders. But you or your AI assistant could make a costly mistake with important info. In a rare but alarming case, Cursor, an AI tool, deleted PocketOS’s company database and its backup. A related 2025 case involved Replit . Other Ways Connected AI Can Go Wrong Travel booking blunder. You ask it to cancel a reservation, and it cancels your entire itinerary. Or you ask it to book a flight on 7/1/27 and it books a nonrefundable ticket on 1/7/27, assuming you were using the European date system and meant January 7, not July 1. Disappearing Files. You ask it to get rid of duplicate files. It deletes an entire folder with a similar name. Calendar Chaos: You ask it to “find a time for everyone” and it reschedules an existing meeting in the wrong time zone, because you were traveling when you wrote the request. I haven’t encountered any of these errors. But these services are still new, so you may encounter occasional bugs or blunders. This article is republished with permission from Wonder Tools , a newsletter that helps you discover the most useful sites and apps.
- MixTranslate Introduces AI Translation Agent That Tells You If Your Translation Is Publish-Ready
MixTranslate Introduces AI Translation Agent That Tells You If Your Translation Is Publish-Ready USA Today
- What every dealmaker should know about the limits of general-purpose AI tools
Connecting AI to deal documents is only the first step. The real advantage comes from building intelligence across the deal life cycle. As artificial intelligence (AI) adoption accelerates across mergers and acquisitions (M&A), many firms are mistaking connectivity for intelligence. Connecting a large language model (LLM) to a traditional virtual data room (VDR) through model [...]
Score: 30🌐 MovesJul 22, 2026https://www.cityam.com/what-every-dealmaker-should-know-about-the-limits-of-general-purpose-ai-tools/ - Speech-to-text API fundamentals: authenticate, poll status, and parse the JSON response
Guide on authenticating, polling, and parsing JSON for AssemblyAI's speech-to-text API.
- XMPro Named as a Sample Vendor for Agent Orchestration category in the Gartner® Hype Cycle™ for AI in IT Operations 2026
XMPro Named as a Sample Vendor for Agent Orchestration category in the Gartner® Hype Cycle™ for AI in IT Operations 2026 azcentral.com and The Arizona Republic
- Before embracing AI, maybe we need more Mayberry
Before embracing AI, maybe we need more Mayberry Austin American-Statesman
- Mygate launches AI assistant to automate financial operations for housing societies
Mygate has introduced MIRA (Mygate Intelligent Response Assistant), an AI-powered assistant designed to automate financial and administrative tasks for resident welfare associations (RWAs) and housing societies. The post Mygate launches AI assistant to automate financial operations for housing societies appeared first on Express Computer .
- Computer and browser use in Codex (5 real examples)
Watch now | 🎙️ I show you exactly how I use browser use and computer use in Codex to QA my app, manage LinkedIn, and shop for Hawaii, including the under-prompting trick that makes frontier models work harder
- How to Let Your Agent Call Dify Workflows Directly
Learn how to invoke existing Dify apps, turning complex business workflows into a single prompt with one human approval.
- Alphabet Posts $98 Billion in Second-Quarter Investment Gains
Alphabet Inc. on Wednesday reported investment gains of $98 billion as part of its second-quarter earnings results.
Score: 30🌐 MovesJul 22, 2026https://www.bloomberg.com/news/articles/2026-07-22/alphabet-posts-98-billion-in-second-quarter-investment-gains - The End Of The Seven-Sins Product Era: AI Must Liberate Agency
The highest form of technology is liberation, not intelligence.
- This is the stock to buy after OpenAI's AI agent goes rogue in a cybersecurity test
Jim Cramer said CrowdStrike is the stock to buy after OpenAI's agentic breach.
- AIAI Deploys Bid Accelerator, Showcasing Its Transformational AI Integration Strategy
AIAI Deploys Bid Accelerator, Showcasing Its Transformational AI Integration Strategy USA Today
- AI Music Without the AI Smell: Kunlun Tech Mureka V9.5 Delivers Score-Worthy Music Through Reflective Reasoning and Agentic Creation
Kunlun Tech Mureka V9.5 with O3 reflective reasoning and MuCo creation agent delivers production-grade AI music that sounds human-made rather than machine-generated.
- Loop Engineering for RAG Generation: Iterate top-k One at a Time
Enterprise Document Intelligence [Vol.1 #8bis] - Two regimes for sending retrieved candidates to the generation brick, the sufficiency signal that picks between them, and the per-question type dispatch that makes it cheap The post Loop Engineering for RAG Generation: Iterate top-k One at a Time appeared first on Towards Data Science .
Score: 30🌐 MovesJul 22, 2026https://towardsdatascience.com/loop-engineering-for-rag-generation-when-top-1-is-enough-when-you-need-top-k/ - The AI Blueprint For Fashion Ecommerce
Fashion ecommerce is entering a new era. The first was about adding intelligence to the customer journey: better search, smarter…
- How AI certification can help employees climb the career ladder
How AI certification can help employees climb the career ladder IT Pro
- Lookout launches tool to expose vulnerable code hidden inside mobile apps
Mobile security company Lookout Inc. today launched the Lookout Mobile Software Exposure Center, a tool that lets organizations continuously identify, assess and prioritize the software exposure risk buried inside the mobile apps running on their employees’ devices. The capability is delivered as a core part of the company’s Lookout Mobile Endpoint Security platform, using the […] The post Lookout launches tool to expose vulnerable code hidden inside mobile apps appeared first on SiliconANGLE .
Score: 28🌐 MovesJul 22, 2026https://siliconangle.com/2026/07/22/lookout-launches-tool-expose-vulnerable-code-hidden-inside-mobile-apps/ - Maharashtra to get India's first AI-powered bird sanctuary
Maharashtra to get India's first AI-powered bird sanctuary YourStory.com
Score: 28🌐 MovesJul 22, 2026https://yourstory.com/ai-story/maharashtra-ai-bird-sanctuary-thane-creek - How to transcribe audio from a mobile app (iOS/Swift, Android/Kotlin, React Native)
Step‑by‑step instructions for transcribing audio in mobile apps across iOS, Android, and React Native.
- Why Claude Code Changed My Workflow?
I used to write code. Now I mostly write plans and review. That sounds like a slogan, but it’s the most honest way I can describe what happened to my day-to-day as an engineer. For a while, Claude Code was “fancy autocomplete” to me: I typed, it guessed, I fixed, and I was still doing all of the thinking. The shift came when I stopped treating it like a tool and started treating it like a coworker one with a specific skill set, a cost, and habits I had to learn to manage. This is the write-up I wish I’d read at the start: the mental model that made everything click, the workflow I actually use now, and the handful of concepts that carry the most weight. The one mental model that unlocked everything Claude Code is two pieces , and confusing them is the source of most early frustration: The harness : the program itself (the CLI, the desktop app, the IDE extension). It touches your files, runs commands, holds your git history and environment. The model : Opus, Sonnet, or Haiku. It only thinks . It cannot touch your machine. Diagrams in this article are from Lydia Hallie’s Claude Code workshop (Frontend Masters). The model never edits a file or runs a command directly. It decides what should happen and emits a “tool call” essentially a request and the harness executes it, then feeds the result back. That back-and-forth is the agentic loop , and it’s what makes this an agent instead of a chatbot. The loop ends when the model replies with plain text and no tool call which is exactly the moment your terminal goes quiet and hands control back to you. Two consequences fall out of this that matter every single day: The model is stateless. It has no memory between calls. Every turn, the harness re-assembles everything : your files, the conversation so far, your CLAUDE.md, your list of skills .. into one big prompt. What you put in that prompt is your usage. A bloated CLAUDE.md or a runaway context window isn't free, it's re-sent and it degrades quality. Once I internalized “the model plans, the harness executes,” the rest of the features stopped feeling like a grab-bag and started feeling like a system. My actual workflow: a five-step pipeline I don’t freestyle prompts anymore. I run a pipeline (built on Matt Pocock’s skills): grill-with-docs: before I write a line, it interrogates my idea against the real documentation. Half the time it surfaces a constraint I hadn’t considered. to-spec: turn the grilled idea into a written spec. to-tickets: break the spec into small, independently-grabbable tickets. implement: build them one at a time. code-review: a dedicated review pass before anything merges. Working with a teammate? This pays off even more. Because to-tickets already splits the work into small, independent issues, you can point Claude at exactly the right slice "only work on the tickets that aren't assigned to my teammate." You each stay in your lane, nothing overlaps, and you sidestep the merge conflicts you'd hit the traditional way, where you're both editing the same thing. It's far more organized. The magic isn’t any single step, it’s that thinking happens before building , and each stage produces an artifact I can review. My job shifted from typing code to being the product manager and the reviewer. Pick the model and the effort on purpose Three models, and the trade-off is capability vs. speed vs. cost: Opus: the deep reasoner. Novel edge cases, conflicting requirements, non-obvious bugs. Slowest and priciest; overkill for simple work. Sonnet: my everyday driver. Features, bug fixes, refactors, tracing errors. Haiku: genuinely good for tasks that don’t need reasoning: renaming, listing, mechanical refactors. Fast and cheap. The subtlety people miss: there’s also an effort level (low / medium / high / max) how hard the model thinks. When a model gets “lazy” and refuses, it’s often just low effort , not too small a model. When Opus rewrites your whole test suite because you asked for a blue button, it’s often max effort , not too big a model. My rule: start with Sonnet, escalate to Opus only if it can’t get it right. Defaulting to “always Opus, max effort” burns limits fast. Plan before you let it code Before implementing anything, I use Plan Mode (Shift+Tab in the CLI, or just ask it to plan). It flips your role: you review the plan, push back, and then it builds. This is where I catch the most mistakes, the plan reveals assumptions and missing pieces before a single file changes. And put verification in the loop : give the model something concrete to check against, a screenshot of the intended UI, an existing test, a type-check. Stop re-typing: skills If you find yourself explaining the same procedure twice, make it a skill, a Markdown file with a reusable procedure: --- name: deploy description: Deploy the app to staging or production. Use when wrapping up a release. --- # Deploy 1. Run the tests. 2. Bundle the app. 3. Deploy to the target environment. The frontmatter (name + description) is always sent to the model it's how Claude decides when to trigger the skill. A vague description means it never fires. The body is the actual procedure, loaded only when the skill runs (“progressive disclosure”). So a long skill costs you nothing until it’s used. Think of it as: description = when to run it, body = what it does. The mindset shift: we’ve gone from prompt engineering to skill engineering . Enforce things with hooks Skills shape behavior, but they can’t guarantee anything. When something absolutely must happen, you want a hook custom logic bound to a point in the agentic loop, like a Git hook but for Claude Code’s lifecycle. The canonical example: type-checking on every edit. // .claude/settings.json { "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", "hooks": [{ "type": "command", "command": "bun run typecheck" }] } ] } } Rule of thumb: if it must be enforced, it’s a hook. If it’s a repeatable flow, it’s a skill. Protect your context: sub-agents Everything above runs in one conversation, and every tool result piles into that context. The more clutter, the worse the model gets at the original task. Sub-agents fix this. A sub-agent is a separate loop with its own context, tools, and system prompt. The main agent spawns it, it works in the background, and only the result comes back, all the noisy intermediate steps never touch your main conversation. The catch: sub-agents use a lot of tokens because they re-establish base context from scratch, and people often don’t realize they’re running. Use the right model for them, and check /usage if your bill looks weird. The counterintuitive lesson: more isn’t better The context window went from 200K tokens to 1M, and my instinct was to celebrate. Wrong instinct. As the window fills, the model loses the thread — too much irrelevant content — and output quality drops . I now /compact or clear and start fresh far more often than I expected to. If you’re starting today The single most useful reframe: treat it like a teammate, not a search box. Plan with it before it writes anything. Give it something to verify its work against. Turn your repeated prompts into skills, and enforce the non-negotiables with hooks. Match the model and effort to the task, and keep your context lean. That’s the real change. I write fewer lines of code than I used to and I ship better software because of it. What’s the one Claude Code habit that changed your workflow? I’d love to hear it. Why Claude Code Changed My Workflow? was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.
Score: 28🌐 MovesJul 22, 2026https://pub.towardsai.net/why-claude-code-changed-my-workflow-269349e06c86?source=rss----98111c9905da---4 - NITI Aayog meets Meta, YouTube, industry bodies on online content blocking rules
NITI Aayog reportedly convened a closed-door meeting with major tech intermediaries and industry bodies to discuss content blocking requirements and transparency timelines under India’s IT Rules. The post NITI Aayog meets Meta, YouTube, industry bodies on online content blocking rules appeared first on MEDIANAMA .
Score: 28🌐 MovesJul 22, 2026https://www.medianama.com/2026/07/223-niti-aayog-content-blocking-meeting-report/ - 'Millennial Genius' China Internet Can't Get Over: Moonshot AI Founder
'Millennial Genius' China Internet Can't Get Over: Moonshot AI Founder Business Insider
Score: 28🌐 MovesJul 22, 2026https://www.businessinsider.com/moonshot-ai-kimi-k3-founder-china-internet-millennial-genius-2026-7 - 3 ways to get your data AI-ready
3 ways to get your data AI-ready IT Pro
Score: 27🌐 MovesJul 22, 2026https://www.itpro.com/technology/big-data/3-ways-to-get-your-data-ai-ready - AI Can Generate Pictures, but It Can Also Help Locate Your Lost Real Photos
Need help finding that photo from six years ago? Google Photos and Gemini can help.
Score: 26🌐 MovesJul 22, 2026https://www.cnet.com/tech/services-and-software/ai-help-locate-your-lost-photos-media/ - AI Consulting Services for Small Business Growth
AI Consulting Services for Small Business Growth USA Today
Score: 26🌐 MovesJul 22, 2026https://www.usatoday.com/press-release/story/37980/ai-consulting-services-for-small-business-growth/ - Yufeng Zhao, Special postdoctoral researcher in Basic Science on the Natural Language Understanding Team, Receives the JSAI 40th Anniversary Best Paper Award
Yufeng Zhao, Special postdoctoral researcher in the Natural Language Understanding Team, has received the “40th Anniversary Best Paper Award (JSAI Anniversary Best Paper Award)” from the Japanese Society for Artificial Intelligence (JSAI).
Score: 25🌐 MovesJul 22, 2026https://aip.riken.jp/news/jsai-40th-anniversary-best-paper-award/?lang=en - I used ChatGPT to learn about World Brain Day — these 7 prompts taught me how to improve my brain health
I used ChatGPT to learn about World Brain Day — these 7 prompts taught me how to improve my brain health Tom's Guide
- I planned an entire weekend getaway using ChatGPT’s voice mode — here’s why it was easier than typing
I planned an entire weekend getaway using ChatGPT’s voice mode — here’s why it was easier than typing Tom's Guide
- IIT Bombay alumni build AI weather platform for Mumbai
IIT Bombay alumni build AI weather platform for Mumbai YourStory.com
Score: 25🌐 MovesJul 22, 2026https://yourstory.com/ai-story/iit-bombay-alumni-ai-weather-platform-mumbai - Transcription webhooks and callbacks: get notified when a transcript is ready
How to use webhooks and callbacks to receive notifications when transcripts finish.
- AI Reviews From Our Experts
AI Reviews From Our Experts PCMag
- A New Book 'The Trust Algorithm' Shows Leaders How to Build Trust in the Age of Generative AI
A New Book 'The Trust Algorithm' Shows Leaders How to Build Trust in the Age of Generative AI azcentral.com and The Arizona Republic
- DropPR.ai Positions PR Distribution as a Core Layer for Brands Competing in AI Search
DropPR.ai Positions PR Distribution as a Core Layer for Brands Competing in AI Search USA Today
- ChatGPT advertising for home services: How contractors win high-intent leads in 2026
ChatGPT advertising for home services: How contractors win high-intent leads in 2026 Miami Herald
- Sparity Earns Microsoft Solutions Partner Designation for Data & AI (Azure)
Sparity Earns Microsoft Solutions Partner Designation for Data & AI (Azure) azcentral.com and The Arizona Republic
- Karini AI Achieves AWS Manufacturing and Industrial Software Competency for Its Agentic AI Foundation Platform
Karini AI Achieves AWS Manufacturing and Industrial Software Competency for Its Agentic AI Foundation Platform azcentral.com and The Arizona Republic
- Nvidia tries again to get gamers to accept DLSS 5 — and doesn't entirely succeed
Nvidia shows how DLSS 5 gives developers control — but many gamers remain skeptical and accusations of 'Slopvidia' abound.
- [Media Coverage] Supervised by Team Director Yoichiro Yamamoto: Newton Special Edition, "Everything You Need to Know About Artificial Intelligence: Latest Edition" (July 21, 2026)
On July 21, 2026, Newton Special Edition: The Complete Guide to Artificial Intelligence – Latest Edition, for which Dr. Yoichiro Yamamoto, Team Director of Biomedical Spatial Science Team, served as one of the supervising editors, was published by
- Mishruh AI Company Profile Funding & Investors
Mishruh AI Company Profile Funding & Investors YourStory.com
- Meta blocks Maktoob Hindi’s Instagram reel on Jantar Mantar protests
Maktoob Hindi’s Instagram reel on the Delhi protests has been geo-blocked in India after Meta received a legal request under the IT Rules, 2021. The publication says the video remains accessible internationally and has been archived. The post Meta blocks Maktoob Hindi’s Instagram reel on Jantar Mantar protests appeared first on MEDIANAMA .
Score: 18🌐 MovesJul 22, 2026https://www.medianama.com/2026/07/223-maktoob-hindi-reel-geo-blocked-india/ - South Korea launches first dating reality show with AI partners
South Korea launches first dating reality show with AI partners The Straits Times
Score: 18🌐 MovesJul 22, 2026https://www.straitstimes.com/asia/east-asia/south-korea-launches-first-dating-reality-show-with-ai-partners - [Paper] Stringological sequence prediction II
Abstract: In a previous paper, we began the study of sequence prediction algorithms adapted to stringological word complexity measures. One measure we considered was left-to-right (most-significant-digit-first) automaticity. Here, we show a statistically and computationally efficient algorithm adapted to the "dual" right-to-left (least-significant-digit-first) automaticity, which turns out to be substantially different for our purpose. We also demonstrate a prediction algorithm for a more expressive measure that we call "arithmetic repetition complexity". In particular, the latter can be used for predicting the so-called mix-automatic sequences. This paper continues my sequence on the new approach to compositional learning, which started with " stringological sequence prediction I ". Curiously, the ARC complexity measure I define here seems related [1] to my control-theoretic complexity measure for polytope MDPs , even though the initial motivation here came from a completely different automata-theoretic angle [2] . ^ Specifically, concatenating words is similar to the "temporal" MDP composition and zipping words is similar to the "spatial" MDP composition . ^ Automata reading time indices in different directions. Discuss
Score: 15🌐 MovesJul 22, 2026https://www.alignmentforum.org/posts/TTei7oq9ndjJFgnsT/paper-stringological-sequence-prediction-ii - Shin Jin-seo defeats top Go AI KataGo to win series
Shin Jin-seo defeats top Go AI KataGo to win series 매일경제