Lars Grammel
lars.grammel@gmail.com
90d · built 2026-05-28
90-day totals
- Commits
- 127
- Grow
- 6.4
- Maintenance
- 22.2
- Fixes
- 1.9
- Total ETV
- 30.4
Where this dev ranks
Percentile against the global top-100 leaderboard (all-time totals).
- By commits
- Top 11 %
- By Growth share
- Top 81 %
30-day trajectory
Last 30 days vs. the 30 days before. Up arrows on Growth and ETV mean improvement; up arrow on Fixes share means more time on fixes (worse).
Daily performance
Daily ETV, stacked by Growth, Maintenance and Fixes.
Work-mix over time
Share of Growth / Maintenance / Fixes over a rolling 7-day window. Reads as 'where is effort flowing right now'.
Bug flow over time
Monthly bug flow attributed to this developer. The left bar (red) is bug impact this dev authored that was addressed in the given month — combining bugs others fixed for them and bugs they fixed themselves. The right bar is fixes they personally shipped that month, split between self-fixes (overlap with the red bar) and fixes done for someone else. X-axis is fix-time, not introduction-time — the Navigara API attributes bugs backward to the author at the moment the fix lands.
- Self-fix share
- 77%
- Bugs you introduced
- 25.8
- Bugs you fixed
- 11.2
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 20 by ETV in the 90-day window.
- 1.9ETVfeat(ai): change type of experimental_context from unknown to generic (#13102) ## Background `experimental_context` for tools and step preparation was introduced in an earlier release without typing (type: `unknown`). Before marking context as stable, it should support smart generic typing for usage in tools, prepareStep, and telemetry. ## Summary Introduce generics on `experimental_context`. Each tool has a `contextSchema` for the tool-specific context. The context on the AI function call is a union of the tool contexts and can have additional properties for `prepareStep` and telemetry. ## Limitations The `experimental_context` setting is optional even when a context is needed, i.e. it will not throw type validation errors unless a context is specified. ## Manual Verification - [x] run and check types on `examples/ai-functions/src/generate-text/openai/tool-call-with-context.ts` - [x] run and check types on `examples/ai-functions/src/stream-text/openai/tool-call-with-context.ts` - [x] run and check types on `examples/ai-functions/src/agent/openai/generate-context.ts` - [x] run and check types on `examples/ai-functions/src/agent/openai/generate-context-call-options.ts` ## Future Work * mark `experimental_context` stable * add `sanitizeContext` function * add `tool` context wrapper for name mapping and safety * add `context` to `StopCondition` parameters * move `ToolSet` into `provider-utils` package * investigate how to fix context optionality limitation * remove `ToolCallOptions` typegithub.com-vercel-ai · 986c6fd5 · 2026-04-02
- 1.2ETVfix: rename onFinish to onEnd (#15245) ## Background We are standardizes on `End` over `Finish`, and results should be accumulative. ## Summary * Renames the final lifecycle callback from onFinish to onEnd for generateText, streamText, Agent, ToolLoopAgent, and WorkflowAgent; onFinish remains as a deprecated alias, with onEnd taking precedence. * Updates final callback result semantics so usage, content, toolCalls, toolResults, files, sources, and warnings aggregate across all steps, while final-step-only data is available through finalStep. * Adds/deprecates the corresponding callback types (GenerateTextOnEndCallback, WorkflowAgentOnEndCallback) and updates telemetry to use the new onEnd event shape. * Updates docs, examples, references, and the AI SDK 7 migration guide to describe the onEnd rename and the new aggregated final event fields.github.com-vercel-ai · e67d80ed · 2026-05-27
- 1.1ETVfeat: add performance statistics (#15241) ## Background Statistics such as tokens per ms and time to first token are important to understand the performance of models and providers. In addition to telemetry, they can also be displayed in user interfaces. ## Summary * add `performance` property to `StepResult` with `tokensPerSecond`, `stepTimeMs`, `responseTimeMs`, `toolExecutionMs`, `timeToFirstTokenMs` * rename `durationMs` on tool execution events to `toolExecutionMs` ## Example Output ``` Step performance: [ { stepTimeMs: 2592.4770839999996, responseTimeMs: 2591.246209, tokensPerSecond: 61.36043709306976, toolExecutionMs: { call_zFG9UMazm5kY2r4q4Mn6LUyx: 0.0625 }, timeToFirstTokenMs: 2339.711542 }, { stepTimeMs: 1228.0632500000002, responseTimeMs: 1226.2540409999997, tokensPerSecond: 35.06614336205071, toolExecutionMs: { call_Ben1pOrejarzcE87EtPbXndv: 0.06979200000023411 }, timeToFirstTokenMs: 873.9773329999998 }, { stepTimeMs: 3674.4792079999997, responseTimeMs: 3673.7040419999994, tokensPerSecond: 100.17137902041159, toolExecutionMs: {}, timeToFirstTokenMs: 3110.819042 } ] ``` ## Manual Verification Run and verify: - [x] `examples/ai-functions/src/generate-text/openai/step-performance.ts` - [x] `examples/ai-functions/src/stream-text/openai/step-performance.ts` ## Future Work * add support in `WorkflowAgent` @gr2mgithub.com-vercel-ai · f4cc8eb7 · 2026-05-13
- 1.1ETVfix: better context type inference (#14186) ## Background Generic context was introduced in #13102 . However, the type inference for the `context` property was not requiring it to be available (no type error was shown when context was not specified). ## Summary * switch from `GenerationContext` approach to separate `USER_CONTEXT` * change context type on `Tool` * update related code ## Manual Verification - [x] check types and remove/experiment with type errors in `examples/ai-functions/src/generate-text/openai/tool-call-with-context.ts` - [x] check types and remove/experiment with type errors in `examples/ai-functions/src/stream-text/openai/tool-call-with-context.ts` - [x] check types and remove/experiment with type errors in `examples/ai-functions/src/agent/openai/generate-context.ts` ## Related Issues Addresses limitation from #13102github.com-vercel-ai · 3ae1786f · 2026-04-10
- 1.0ETVfeat(ai): separate toolsContext from context (#14515) ## Background Having a unified context represents a security issue. Adversarial 3rd party tools might be able to access general context information as well as context from other tools. ## Summary * separate runtime context from tools context * segregate tools context by tool (each tool can only access the context that has been explicitly provided for it) ## Example ```ts const weather = tool({ inputSchema: z.object({ location: z.string(), }), contextSchema: z.object({ apiKey: z.string(), }), execute: async ( { location }, { context: { apiKey } }, ) => { return getWeather(location, apiKey); }, }); const result = await generateText({ model: yourModel, tools: { weather }, toolsContext: { weather: { apiKey: process.env.WEATHER_API_KEY!, }, }, }); ``` ## Manual Verification - [x] run / test `examples/ai-functions/src/generate-text/openai/tool-call-with-context.ts` - [x] run / test `examples/ai-functions/src/stream-text/openai/tool-call-with-context.ts` - [x] run / test `examples/ai-functions/src/agent/openai/generate-context.ts` ## Future Work * validate the context against the tool context schema * rename context to runtimeContext * introduce sensitiveContext filtering on tool * introduce sensitiveRuntimeContext filtering ## Related Issues Builds on #14186 and #13102github.com-vercel-ai · 083947bd · 2026-04-16
- 1.0ETVfix(ai): fix auto-complete on provider registry and custom provider (#14811) ## Background Autocomplete on the provider registry stopped working. Most likely caused by the changes in #13001 ## Summary * restored auto-complete functionality * add type tests * add support of all model versions incl. string to CustomProvider ## Manual Verification Check auto-completes and errors in: - [x] `examples/ai-functions/src/registry/setup-registry.ts` ## Related Issues Fixes #14780 --------- Co-authored-by: Felix Arntz <felix.arntz@vercel.com>github.com-vercel-ai · 6147cdff · 2026-04-30
- 1.0ETVrefactoring: rename tool execution events (#14589) ## Background The tool event can be improved as follows: - Align event names with start/end nomenclature. - Remove unnecessary `On` prefix from event. - Change `Call` to `Execution` to emphasize that the event is about tool execution. ## Summary * rename `OnToolCallStartEvent` to `ToolExecutionStartEvent` * rename `OnToolCallFinishEvent` to `ToolExecutionEndEvent` * extract `OnToolExecutionStartCallback` and replace StreamText/GenerateText/ToolLoopAgent variants * extract `OnToolExecutionEndCallback` and replace StreamText/GenerateText/ToolLoopAgent variants * rename `experimental_onToolCallStart` to `experimental_onToolExecutionStart` * rename `experimental_onToolCallFinish` to `experimental_onToolExecutionEnd` * introduce `filterNullable` helper function in provider utils * add `_internal` to `ToolLoopAgentSettings` for testabilitygithub.com-vercel-ai · eea8d98d · 2026-04-17
- 0.8ETVchore: rename experimental_context to context (#14050) ## Background Generic typing was added to `experimental_context` in #13102 . With this feature in place, `context` is now stable and can be renamed. ## Summary * rename `experimental_context` to `context` ## Future Work - type context in `core-events` ## Related Issues Builds on #13102github.com-vercel-ai · 7e26e81d · 2026-04-07
- 0.7ETVfeat(ai): add sensitiveRuntimeContext option (#14757) ## Background The `runtimeContext` can contain information that should not be exposed to telemetry, e.g. credentials. ## Summary Add concept of sensitive runtime context that allows users to restrict which runtime context properties are being sent to telemetry (opt-out). * introduce `SensitiveContext` type * introduce `sensitiveRuntimeContext` option on `generateText`, `streamText`, and `ToolLoopAgent` * restrict `activeTools` to strings and introduce `ActiveTools` helper type * rename `filter-active-tool.ts` to `filter-active-tools.ts` ## Manual Verification Run examples and verify that sensitive context is not logged by telemetry. - [x] generateText `examples/ai-functions/src/telemetry/console/generate-text.ts` - [x] streamText `examples/ai-functions/src/telemetry/console/stream-text.ts` - [x] ToolLoopAgent `examples/ai-functions/src/telemetry/console/tool-loop-agent.ts` ## Future Work * implement `sensitiveContext` for tools ## Related Issues Builds on #14536github.com-vercel-ai · 51ce2327 · 2026-04-28
- 0.7ETVfeat: sandbox shell execution abstraction (#14949) ## Background Many agents are using filesystems through shell and file read/write tools, often in separate sandbox environments. These agents are so common that a first-class sandbox abstraction would be beneficial. ## Summary * add `Sandbox` type * add `sandbox` option to `generateText`, `streamText`, `ToolLoopAgent` * make sandbox available in `ToolExecutionOptions` ## Example Tool definition: ```ts import { tool } from 'ai'; import { z } from 'zod'; export function sandboxShellTool() { return tool({ description: 'Run a shell command', inputSchema: z.object({ command: z.string(), }), execute: async ({ command }, { sandbox }) => { // TODO figure out type inference to turn the runtime error into a type error if (!sandbox) { throw new Error('Sandbox is not available'); } return sandbox.executeCommand({ command }); }, }); } ``` Agent definition: ```ts import { openai } from '@ai-sdk/openai'; import { ToolLoopAgent } from 'ai'; import { sandboxShellTool } from '../../tools/sandbox-shell-tool'; export const sandboxAgent = new ToolLoopAgent({ model: openai('gpt-5.5'), tools: { shell: sandboxShellTool(), }, prepareCall: ({ sandbox, ...rest }) => ({ ...rest, instructions: `You are a helpful assistant that can run shell commands.\n` + `You are operating in the following sandbox: ${sandbox?.description}`, }), }); ``` Agent call: ```ts import { Bash } from 'just-bash'; import { JustBashSandbox } from '../../sandbox/just-bash-sandbox'; import { sandboxAgent } from './sandbox-agent'; const sandbox = new JustBashSandbox( new Bash({ cwd: '/home/user', }), ); const result = await sandboxAgent.stream({ prompt: 'Create a file named greeting.txt with a short greeting, then list the files and show the file contents.', sandbox, }); ``` ## Manual Verification - [x] agent - generate `src/agent/openai/generate-local-sandbox` - [x] agent - stream `src/agent/openai/stream-local-sandbox` - [x] test with ui `examples/ai-e2e-next/app/chat/sandbox/page.tsx` ## Future Work * read/write files in sandboxes * explore generic typing of sandbox tools * move sandbox shell tool into ai package * allow choosing a sandbox in prepareStep * add timeout to executeCommand * figure out sandbox streaming * need onFinalize callback (or something) that is always invoked (on finish, abort, error etc) --------- Co-authored-by: nicoalbanese <gcalbanese96@gmail.com>github.com-vercel-ai · 3015fc36 · 2026-05-07
- 0.7ETVfeat(ai): automatic tool approval (#14643) ## Background Many user-facing agents, e.g. coding agents, allow users to set up default approvals for certain actions (e.g. executing specific shell commands). In such cases, there needs to be a way to automatically approve or deny the execution of certain tool calls. ## Summary Support automatic approval or denial of tool call executions. * tool approval configuration return a `ToolApprovalStatus`, which can be `'not-applicable' | 'approved' | 'denied' | 'user-approval'` * support automatic approval ('approved', 'denied') in `streamText` and `generateText` * add optional `isAutomatic` flag to `ToolApprovalRequest` to indicate when there are automatic responses ## Example ```ts const agent = new ToolLoopAgent({ model: openai('gpt-5.4-mini'), // context engineering required to make sure the model does not retry // the tool execution if it is not approved for a particular tool call: instructions: 'When a tool call was not approved by the user, ' + 'do not retry the tool call with the same input.' + 'Just say that the tool execution was not approved.' + 'You can call a denied tool call with a different input.', tools: { weather: weatherTool }, toolApproval: { weather: ({ location }) => { const locationLower = location.toLowerCase(); if (locationLower.includes('san francisco') || locationLower === 'sf') { return 'approved'; } if (locationLower.includes('new york') || locationLower === 'nyc') { return 'denied'; } return 'user-approval'; }, }, }); ``` ## Limitations * UI messages do not support automatic tool approvals yet. * Automatic tool approvals do not support approval reasons yet. ## Manual Verification * [x] generateText `examples/ai-functions/src/generate-text/openai/tool-approval.ts` * [x] streamText `examples/ai-functions/src/stream-text/openai/tool-approval.ts` * [x] agent `examples/ai-functions/src/agent/openai/generate-tool-approval.ts` ## Future Work * add automatic tool approvals to UI messages * support reason in automatic accept/deny ## Related Issues Build on #14642github.com-vercel-ai · fc920551 · 2026-04-21
- 0.7ETVfeat(ai): add toolNeedsApproval option (#14480) ## Background You may want to enable or disable tool approvals for specific tools, irrespective of the tool approval setting on the tool itself. This is particularly relevant for 3rd party tools where you cannot control the `needsApproval` setting without wrapping the tool. ## Summary Introduce `toolNeedsApproval` option on `generateText`, `streamText`, and `ToolLoopAgent`. The `toolNeedsApproval` option takes precedence over the `needsApproval` property that might be defined on a specific tool. ## Example ```ts const result = await generateText({ // ... tools: { weather }, toolNeedsApproval: { weather: true, // or an approval function }, }); const agent = new ToolLoopAgent({ // ... tools: { weather: weatherTool }, toolNeedsApproval: { weather: true }, }); ``` ## Limitations Provider-executed tools will get executed provider-side without considering the tool approval setting. ## Manual Verification - [x] run / test `examples/ai-functions/src/generate-text/openai/tool-approval-user-defined.ts` - [x] run / test `examples/ai-functions/src/stream-text/openai/tool-approval-user-defined.ts` - [x] run / test `examples/ai-functions/src/agent/openai/generate-tool-approval.ts` ## Future Work * introduce `isProviderExecuted` flag on tools and exclude from approval list * support a single catch all function for `toolNeedApproval`github.com-vercel-ai · 2a9c1442 · 2026-04-16
- 0.6ETVrefactoring: move tool-call, tool-approval, tool-result transformation into create-stream-text-part-transformation (#13607) ## Background We are working towards better support for custom loop control. For this, we are separating out individual reusable functions from streamText. As a first step, we need to separate transformation steps such that each transformation has a single responsibility. ## Summary Move tool-call, tool-approval, tool-result transformation into create-stream-text-part-transformation. ## Related Issues towards #13570github.com-vercel-ai · b53a96fd · 2026-03-19
- 0.6ETVfeat(ai): add experimental_refineToolInput option to ToolLoopAgent, generateText, streamText (#15000) ## Background Different LLM provider might generate slightly different tool inputs for the same tool input type, e.g. using empty string instead of `null`. Tools might come from 3rd party providers, so the input schemas might not support refinement. ## Summary Add an experimental `refineToolInput` option to `ToolLoopAgent`, `generateText`, `streamText` that can be used to modify the tool inputs as long as the expected type is retained. ## Manual Verification Execute examples and check tool inputs: - [x] `examples/ai-functions/src/generate-text/openai/refine-tool-input.ts` - [x] `examples/ai-functions/src/steam-text/openai/refine-tool-input.ts`github.com-vercel-ai · 5588abdc · 2026-05-05
- 0.6ETVfeat: add timeBetweenOutputTokensMs stats (#15310) ## Background Advanced applications need detailed tracking of token performance to understand UX behavior of streams. ## Summary Add `timeBetweenOutputTokensMs` stats.github.com-vercel-ai · 6cca1126 · 2026-05-27
- 0.5ETVfeat(ai): access runtime context in tool approval functions (#14692) ## Background Runtime context can hold additional typed information (agent state) that can be useful in deciding whether to automatically approve tool executions. ## Summary * rename `context` to `toolContext` on `SingleToolApprovalFunction` * add `runtimeContext` to `SingleToolApprovalFunction` and `GenericToolApprovalFunction` ## Manual Verification - [x] run `examples/ai-functions/src/agent/openai/generate-tool-approval-generic.ts` ## Related Issues Builds on #14690 and #14643github.com-vercel-ai · 37d69b24 · 2026-04-22
- 0.5ETVrefactoring: restructure Tool types (#14849) ## Background Different types of tools can have different available options. Currently we expose options on tool types that do not support it, e.g. execute on provider executed tools. ## Summary Refactor the `Tool` type into a union of `FunctionTool`, `DynamicTool`, `ProviderDefinedTool`, and `ProviderExecutedTool`. Expose the new types. Add type tests. The goal is to create a foundation for further refactoring and option restrictions. ## Future Work * restrict options available on specific tool types moregithub.com-vercel-ai · b6783daf · 2026-04-30
- 0.5ETVrefactoring: remove real-time delays in unit tests (#14728) ## Background Unit tests should run without any delays. However, we use `delay` and `setTimeout` in our tests and production code, leading to slower running tests. ## Summary * upgrade `vitest` to `4.1.5` everywhere * add ci test setup patch for codemod testing to prevent test timeouts * use `delay` instead of `setTimeout` * use `vi.useFakeTimers()` and `vi.useRealTimers()` consistently in tests * advance the simulated clock with `vi.advanceTimersByTimeAsync`github.com-vercel-ai · befb78c8 · 2026-04-28
- 0.5ETVchore(ai): simplify unified telemetry creation (#14386) ## Background Generics are not necessary in `getGlobalTelemetryIntegration`. The two calls for creating a unified telemetry can be reduced to one. ## Summary * Remove generics from `getGlobalTelemetryIntegration` * Rename `getGlobalTelemetryIntegration` to `createUnifiedTelemetry` * Single function instead of two functions for creating unified telemetry * Remove `bindTelemetryIntegration` export ## Related Issues Follow up from #14329github.com-vercel-ai · 57bf606b · 2026-04-13
- 0.5ETVfix(ai): reject system messages in messages or prompt by default (opt-in) (#14752) ## Background For historical and convenience reasons, system messages can be part of user messages or prompts, e.g. to allow interleaving regular messages and system messages. However, this creates a prompt injection risk where the user (e.g. by modifying the messages in a web ui) can override or set the system prompt. In most cases, it should only be possible to set the system prompt via the system (or instructions) property, and users should not be able to inject system messages. ## Summary * throw `InvalidPromptError` when there are system messages in the messages or prompt options * add `allowSystemInMessages` option for opting into allowing system messages in messages or prompt options ## Future Work * add `allowSystemInMessages` opt-in support to `WorkflowAgent` (if desired) @gr2m ## Related Issues Issue reported in #14749github.com-vercel-ai · 4e095b06 · 2026-04-28