Repository: openai/openai-agents-js (2025-08-14T21:04:16Z)

Issue:
[Type Definitions] Types mismatch between `RunResult` and `RunState`
### Please read this first

- **Have you read the docs?** [Agents SDK docs](https://openai.github.io/openai-agents-js/)
- **Have you searched for related issues?** Others may have faced similar issues.

### Describe the bug

`RunState` cannot be used to instantiate a `RunResult` even with the same generic types.

### Debug information

- Agents SDK version: (e.g. `v0.0.14`)
- Runtime environment (e.g. `Node.js 22.16.0`)

### Repro steps

See [TS Playground Reproduction](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAbwEoFcB2BlGBDGBTAGjlTSTwGcUAbGAgQQHM80YBfOAMyghDgHIAAhDDNswAPTYmLcnwBQcgMYQ05eNjQBPAMIr8ADxgAuOBs1wAvIlYLlq9dJhW0eAO5xGzGAB4zRPgYwfAB8ABQIcnBwaNggeCZ8ACoUQQRyrACUtipqcHj6YFTAisAwWLh4ltFuxOjl+L5aRJ4sjZr+gSFhZros+bT8wGhgKKmmjkQAjAAMWUo58PmFxaVklDRVLu4ka9Q+fh6ObR39XaFLRSVlOPhzdrlDHHhQUHgAJvWVzjUkn6E9en6-iGIzGUi8U1m2XscEez1eb12G2+23QSJgoThL3enwyQA)

Updated a more common usage pattern with type inference:
```ts
const inferredState = new RunState(anyContext, 'input', agent, 10)

const inferredResult = new RunResult(inferredState)
```

I believe this would be how the constructors or `fromString` are used the most.

### Expected behavior

There should be no errors.

### Possible Fix

Add an extra generic type parameter in `RunResult`:

```
TAgentOutputType extends AgentOutputType
```

A public property to get `history` items from a `RunState` without the need to construct `RunResult`
Sometimes instead of passing a complete `RunState` to resume the execution, I might want to modify or build upon the current items in the state and currently, the only public facing API is through `RunResult.history`:

```ts
new RunResult(state).history
```

but there is some type mismatch mentioned [here](#278) so some awkward type casting using `any` is necessary.

It would be nice if we could have something like:

```ts
RunState.fromString(str).history
```


Discussion:
Thanks for providing the Playground repro (just tried it out).  Agree the error messages are unexpected, but (somewhat surprisingly) the two classes are behaving exactly as intended. 

`RunResult<TContext, TAgent>` is meant to be a thin, read‑only view over a finished run. All info about the agent’s output is already encoded in the second type parameter.  Because, `TAgent` itself carries `TOutput`, adding a third generic type argument would be redundant as every call site would have to repeat the same type twice e.g., `RunResult<MyCtx, MyAgent, "text">`.  Woud also be regressive for inference as TS would struggle to infer 3 independent generics from a single value (and so forcing us to annotate manually)

In the above TS Playground example TS cannot infer that the agent’s concrete output type flows through `RunState` into `RunResult`, because RunState was declared more loosely, however, that is deliberate to allow a runner to upgrade/downgrade agents during a long‑lived conversation but it does mean we occasionally need to help the compiler

This is good f/b though - eventually this could be addressd by inference helpers but in the short term maybe a docs push with a short “Type‑inference tips” section that explains when annotations are needed and how to avoid such scenarios.

I did make a new snippet you can try out and the only change from your original file is just one intentional widening cast that lets the compiler know the runner utilities can accept any agent output type (even though your agent still only returns "text").  

[Revised TS Playground](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAbwFBzgJQK4DsDKMCGMApgDQrrZpEDOGANjGagIIDmRWj5bHMA8hhhhBAFQCeYUqgD00uACJiADxjy4AHwUArahCxrNgMgIkAXzgAzKBBBwA5AAEIkrPmDT87TtVsBuJEhgJIjhmLDEBIUEeTgAeAGE4AF44fDCAPiSQzxh4kizeCOEYcUk0vyQAYz1qeFSxOL1lGAAuFLDMhBNyqqwalOzMrCIAd3zYurzbJts0gApkVBcQIlbbERoYWzITAEpy2Thh4AATDjg9CuDCOBgAC2CAIwhsY-woMThK6trsgDFoTBYIZQTIeXgpaghMKFKLZGJ1Mr+Hp9IhKMB0YAVYAwPCEYLJIajQG44jwsJ5ULhQRFaI5BFzch1BqcVFcVC2YBYIpbRl-AHYYFMOAARgADEg9kjvnBUejMdiqLQGIMRhQsIr6HTyVCqZEYLSyWI0nNZRisTiCMRJV9evBOeYiFAoERjiTgiqidg3bMmY1WZNOdy8mDOP8oIDBSLRZLkXasA6nS6NcqCarAcmYLN7Y7na7LURJUA)
> Thanks for providing the Playground repro (just tried it out). Agree the error messages are unexpected, but (somewhat surprisingly) the two classes are behaving exactly as intended.
> 
> `RunResult<TContext, TAgent>` is meant to be a thin, read‑only view over a finished run. All info about the agent’s output is already encoded in the second type parameter. Because, `TAgent` itself carries `TOutput`, adding a third generic type argument would be redundant as every call site would have to repeat the same type twice e.g., `RunResult<MyCtx, MyAgent, "text">`. Woud also be regressive for inference as TS would struggle to infer 3 independent generics from a single value (and so forcing us to annotate manually)
> 
> In the above TS Playground example TS cannot infer that the agent’s concrete output type flows through `RunState` into `RunResult`, because RunState was declared more loosely, however, that is deliberate to allow a runner to upgrade/downgrade agents during a long‑lived conversation but it does mean we occasionally need to help the compiler
> 
> This is good f/b though - eventually this could be addressd by inference helpers but in the short term maybe a docs push with a short “Type‑inference tips” section that explains when annotations are needed and how to avoid such scenarios.
> 
> I did make a new snippet you can try out and the only change from your original file is just one intentional widening cast that lets the compiler know the runner utilities can accept any agent output type (even though your agent still only returns "text").
> 
> [Revised TS Playground](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAbwFBzgJQK4DsDKMCGMApgDQrrZpEDOGANjGagIIDmRWj5bHMA8hhhhBAFQCeYUqgD00uACJiADxjy4AHwUArahCxrNgMgIkAXzgAzKBBBwA5AAEIkrPmDT87TtVsBuJEhgJIjhmLDEBIUEeTgAeAGE4AF44fDCAPiSQzxh4kizeCOEYcUk0vyQAYz1qeFSxOL1lGAAuFLDMhBNyqqwalOzMrCIAd3zYurzbJts0gApkVBcQIlbbERoYWzITAEpy2Thh4AATDjg9CuDCOBgAC2CAIwhsY-woMThK6trsgDFoTBYIZQTIeXgpaghMKFKLZGJ1Mr+Hp9IhKMB0YAVYAwPCEYLJIajQG44jwsJ5ULhQRFaI5BFzch1BqcVFcVC2YBYIpbRl-AHYYFMOAARgADEg9kjvnBUejMdiqLQGIMRhQsIr6HTyVCqZEYLSyWI0nNZRisTiCMRJV9evBOeYiFAoERjiTgiqidg3bMmY1WZNOdy8mDOP8oIDBSLRZLkXasA6nS6NcqCarAcmYLN7Y7na7LURJUA)

Thanks for the updates. The root of my requirement is actually to get the `history` of a captured state and the only public API I can find is through `RunResult`. 

In fact the logic of getting `result.history` is quite simple and straightforward so maybe this can justify another feature request to get the `history` items of a `RunState`.
Thanks for the clarification!  you’re right that the only public API for accessing history is currently through `RunResult`.  

Just want to add some context: `RunState` is intentionally a persistence artefact, and it captures just enough info for the runtime to resume or continue a run. Any (human) readable helpers (history, output, etc.) live on `RunResult`, which is a thin, read‑only front we could construct at any time, e.g.

```
import { RunResult } from "@openai/agents-core";
const history = new RunResult(state).history;   
```
This separation helps keep the persistence format stable while allowing the developer-facing API (i.e., `RunResult`) to evolve independently.

However, I can definitely see how a first‑class `RunState.history` could simplify tools that operate on intermediate or paused states. If you think this would be broadly useful, a suggestion would be to please open a feature‑request issue and link back to this thread. That will give the community a chance to weigh in. I’d be happy to submit a PR based on further feedback.
> Thanks for the clarification! you’re right that the only public API for accessing history is currently through `RunResult`.
> 
> Just want to add some context: `RunState` is intentionally a persistence artefact, and it captures just enough info for the runtime to resume or continue a run. Any (human) readable helpers (history, output, etc.) live on `RunResult`, which is a thin, read‑only front we could construct at any time, e.g.
> 
> ```
> import { RunResult } from "@openai/agents-core";
> const history = new RunResult(state).history;   
> ```
> 
> This separation helps keep the persistence format stable while allowing the developer-facing API (i.e., `RunResult`) to evolve independently.
> 
> However, I can definitely see how a first‑class `RunState.history` could simplify tools that operate on intermediate or paused states. If you think this would be broadly useful, a suggestion would be to please open a feature‑request issue and link back to this thread. That will give the community a chance to weigh in. I’d be happy to submit a PR based on further feedback.

Absolutely, here is the feature request https://github.com/openai/openai-agents-js/issues/293

Thanks for sharing this. I need to better understand what the input string data, which can be passed to the `fromString` and what's the actual scenario in your mind. Could you elaborate on that? I could imagine there should be some specific use case, but I am unable to guess what it is from given information.
> Thanks for sharing this. I need to better understand what the input string data, which can be passed to the `fromString` and what's the actual scenario in your mind. Could you elaborate on that? I could imagine there should be some specific use case, but I am unable to guess what it is from given information.

@seratch  The use case is very similar to the example on this page https://openai.github.io/openai-agents-js/guides/results/#inputs-for-the-next-turn but instead of accessing the immediate `RunResult`, I will be reading a serialized `RunState` from the database and resume from there.

Also, the "input string data" you mentioned, it's from `RunResult.state.toString()` documented [here](https://openai.github.io/openai-agents-js/openai/agents/classes/runstate/#tostring). I serialize the run state and save it to the database and use it later.
Thanks for your quick reply!



Patch:
diff --git a/.changeset/expose-runstate-history.md b/.changeset/expose-runstate-history.md
new file mode 100644
index 00000000..8983e90e
--- /dev/null
+++ b/.changeset/expose-runstate-history.md
@@ -0,0 +1,5 @@
+---
+'@openai/agents-core': patch
+---
+
+feat: expose the `history` getter on `RunState` to access input and generated items.
diff --git a/packages/agents-core/src/runState.ts b/packages/agents-core/src/runState.ts
index a18e6493..cbb14d1b 100644
--- a/packages/agents-core/src/runState.ts
+++ b/packages/agents-core/src/runState.ts
@@ -12,6 +12,7 @@ import {
 } from './items';
 import type { ModelResponse } from './model';
 import { RunContext } from './runContext';
+import { getTurnInput } from './run';
 import {
   AgentToolUseTracker,
   nextStepSchema,
@@ -327,6 +328,15 @@ export class RunState<TContext, TAgent extends Agent<any, any>> {
     this._trace = getCurrentTrace();
   }
 
+  /**
+   * The history of the agent run. This includes the input items and the new items generated during the run.
+   *
+   * This can be used as inputs for the next agent run.
+   */
+  get history(): AgentInputItem[] {
+    return getTurnInput(this._originalInput, this._generatedItems);
+  }
+
   /**
    * Returns all interruptions if the current step is an interruption otherwise returns an empty array.
    */


Test patch:
diff --git a/packages/agents-core/test/runState.test.ts b/packages/agents-core/test/runState.test.ts
index 4d9a57ef..c6c67765 100644
--- a/packages/agents-core/test/runState.test.ts
+++ b/packages/agents-core/test/runState.test.ts
@@ -8,7 +8,10 @@ import {
 } from '../src/runState';
 import { RunContext } from '../src/runContext';
 import { Agent } from '../src/agent';
-import { RunToolApprovalItem as ToolApprovalItem } from '../src/items';
+import {
+  RunToolApprovalItem as ToolApprovalItem,
+  RunMessageOutputItem,
+} from '../src/items';
 import { computerTool } from '../src/tool';
 import * as protocol from '../src/types/protocol';
 import { TEST_MODEL_MESSAGE, FakeComputer } from './stubs';
@@ -31,6 +34,32 @@ describe('RunState', () => {
     expect(state._context.context).toEqual({ foo: 'bar' });
   });
 
+  it('returns history including original input and generated items', () => {
+    const context = new RunContext();
+    const agent = new Agent({ name: 'HistAgent' });
+    const state = new RunState(context, 'input', agent, 1);
+    state._generatedItems.push(
+      new RunMessageOutputItem(TEST_MODEL_MESSAGE, agent),
+    );
+
+    expect(state.history).toEqual([
+      { type: 'message', role: 'user', content: 'input' },
+      TEST_MODEL_MESSAGE,
+    ]);
+  });
+
+  it('preserves history after serialization', async () => {
+    const context = new RunContext();
+    const agent = new Agent({ name: 'HistAgent2' });
+    const state = new RunState(context, 'input', agent, 1);
+    state._generatedItems.push(
+      new RunMessageOutputItem(TEST_MODEL_MESSAGE, agent),
+    );
+
+    const restored = await RunState.fromString(agent, state.toString());
+    expect(restored.history).toEqual(state.history);
+  });
+
   it('toJSON and toString produce valid JSON', () => {
     const context = new RunContext();
     const agent = new Agent({ name: 'Agent1' });