1
00:00:00,300 --> 00:00:01,340
Okay, we're rolling.

2
00:00:01,920 --> 00:00:05,480
Thanks to Jellypod for helping make this
daily show a reality.

3
00:00:06,360 --> 00:00:12,620
Today is one change that matters if you
run Codex with parallel subagents and you

4
00:00:12,680 --> 00:00:13,760
look at your token bill.

5
00:00:15,020 --> 00:00:20,600
Pull request 55587, merged October 20th,
authored by

6
00:00:20,900 --> 00:00:22,400
rm-openai.

7
00:00:23,220 --> 00:00:28,960
The title is "Allow callers to control
prompt cache keys independently of session

8
00:00:29,020 --> 00:00:29,360
IDs."

9
00:00:30,120 --> 00:00:31,000
Here's the mechanism.

10
00:00:31,580 --> 00:00:36,440
Codex sends a prompt_cache_key with model
requests, and historically that key was

11
00:00:36,480 --> 00:00:37,880
derived from the session ID.

12
00:00:38,480 --> 00:00:39,880
One session, one key.

13
00:00:40,520 --> 00:00:42,200
That's fine for a single conversation.

14
00:00:42,760 --> 00:00:47,420
Multi agent V2 breaks it, because every
subagent gets its own session manager and

15
00:00:47,460 --> 00:00:48,820
its own session ID.

16
00:00:49,420 --> 00:00:53,000
So a worker that shares thousands of
tokens of repo context,

17
00:00:53,340 --> 00:00:58,180
system instructions, and tool definitions
with ten siblings still sends a different

18
00:00:58,240 --> 00:00:58,820
cache key.

19
00:00:59,460 --> 00:01:04,620
There's an open issue in the pi repo,
number 6468, describing exactly this pattern

20
00:01:04,660 --> 00:01:10,020
in coding agent SDKs: fan out sends a
different prompt cache key for each subagent.

21
00:01:10,608 --> 00:01:14,948
And the cost side comes from OpenAI's
prompt caching docs.

22
00:01:15,928 --> 00:01:22,908
For GPT 5.6 and later, cache writes cost
1.25 times

23
00:01:23,008 --> 00:01:27,728
the standard uncached input rate on the
default thirty minute retention.

24
00:01:29,008 --> 00:01:34,328
Cache reads are heavily discounted, in the
range of 90 to 95 percent off.

25
00:01:35,548 --> 00:01:41,808
So if your key differs per worker, each
worker can pay the write premium on a prefix

26
00:01:41,928 --> 00:01:43,448
that was already identical.

27
00:01:44,448 --> 00:01:46,328
Same bytes, paid for repeatedly.

28
00:01:47,688 --> 00:01:52,508
That's the interpretation of the issue
plus the docs, not a measured number from

29
00:01:52,548 --> 00:01:57,388
this pull request, so check your own usage
before promising anyone savings.

30
00:01:58,385 --> 00:02:04,025
So what changed is that StartThreadOptions
now exposes PromptCacheKey with three

31
00:02:04,125 --> 00:02:04,625
policies.

32
00:02:05,205 --> 00:02:08,244
Default keeps the old behavior, the
session derived key.

33
00:02:08,864 --> 00:02:10,765
Custom lets you pass your own string.

34
00:02:11,385 --> 00:02:16,025
Omit strips prompt_cache_key from outbound
model requests entirely.

35
00:02:16,733 --> 00:02:19,333
The important design choice is the
separation.

36
00:02:20,093 --> 00:02:24,673
Per the pull request, session identity
headers stay independent of this policy.

37
00:02:25,593 --> 00:02:30,793
So your tracing IDs, connection identity,
and thread persistence don't change when

38
00:02:30,833 --> 00:02:31,793
you set a custom key.

39
00:02:32,713 --> 00:02:36,793
You're only touching the field the model
API uses for cache routing.

40
00:02:37,653 --> 00:02:41,593
And the policy propagates to child agents,
delegated sessions,

41
00:02:42,013 --> 00:02:43,393
and Guardian review sessions.

42
00:02:44,273 --> 00:02:48,413
You set it once on the parent thread and
spawned subagents inherit it.

43
00:02:48,987 --> 00:02:49,967
Let's make it concrete.

44
00:02:50,407 --> 00:02:54,887
Say you run an orchestrator that fans out
eight workers over the same repository.

45
00:02:55,427 --> 00:02:59,207
Each gets the same instructions and tools,
then a different slice of the task.

46
00:02:59,767 --> 00:03:04,527
You'd start the parent thread with
PromptCacheKey Custom, and pick a key built from

47
00:03:04,607 --> 00:03:08,347
stable things: something like workflow,
then your project name,

48
00:03:08,547 --> 00:03:09,827
then an instruction version.

49
00:03:10,347 --> 00:03:14,227
For example, workflow colon myrepo colon
v1.

50
00:03:14,867 --> 00:03:17,027
Bump the version when you change the
shared instructions.

51
00:03:17,587 --> 00:03:21,987
Then the first worker pays the write, and
later workers can read the warmed prefix

52
00:03:22,107 --> 00:03:23,167
instead of writing again.

53
00:03:23,830 --> 00:03:25,570
Keep the key low cardinality.

54
00:03:26,030 --> 00:03:31,570
OpenAI's caching docs warn that on older
models, sending more than roughly fifteen

55
00:03:31,610 --> 00:03:35,810
requests per minute under a single key can
overflow a machine's capacity.

56
00:03:36,370 --> 00:03:40,590
At the other extreme, a key that's unique
per request destroys your hit rate.

57
00:03:41,310 --> 00:03:46,810
So you want a bounded key per shared
prefix, not per worker and not one global key

58
00:03:46,850 --> 00:03:47,450
for everything.

59
00:03:48,250 --> 00:03:51,450
If you run several unrelated pipelines,
give each its own key.

60
00:03:52,200 --> 00:03:53,760
Second use case is Omit.

61
00:03:54,260 --> 00:03:57,680
If you point Codex at a custom Responses
compatible gateway,

62
00:03:58,080 --> 00:04:02,460
think a proxy in front of a local model,
some of those can misroute or reject

63
00:04:02,500 --> 00:04:05,140
requests with a prompt_cache_key they
don't expect.

64
00:04:05,740 --> 00:04:08,780
Omit lets you drop the field without
touching how sessions work.

65
00:04:09,180 --> 00:04:10,200
Everything else stays the same.

66
00:04:10,840 --> 00:04:15,460
The exact JSON spelling over app server
RPC, check the generated schema in your

67
00:04:15,500 --> 00:04:18,000
build, since I'm not going to guess field
names on air.

68
00:04:18,622 --> 00:04:21,822
Now the caveats, and there are three.

69
00:04:22,962 --> 00:04:29,022
First, the one the commit itself calls
out: hosts must reapply the policy when

70
00:04:29,082 --> 00:04:30,862
resuming a thread from storage.

71
00:04:31,682 --> 00:04:36,262
If you resume a saved thread, don't assume
your custom key came back with it.

72
00:04:36,902 --> 00:04:41,922
Your harness has to pass the policy again,
otherwise you're likely back on the

73
00:04:41,982 --> 00:04:46,082
default and your fan out quietly returns
to per session keys.

74
00:04:46,922 --> 00:04:50,842
Worth adding a test that checks the
outbound request on resume.

75
00:04:51,760 --> 00:04:54,260
Second, the key only helps with routing.

76
00:04:54,620 --> 00:04:57,180
It doesn't make mismatched prompts match.

77
00:04:57,780 --> 00:05:02,620
If tool schemas differ, reasoning effort
differs, or the ordering of developer

78
00:05:02,680 --> 00:05:06,720
messages diverges before the cache
breakpoint, you'll still miss,

79
00:05:07,100 --> 00:05:08,040
whatever key you send.

80
00:05:08,580 --> 00:05:14,200
So keep the shared prefix byte for byte
identical, and put the per worker task text

81
00:05:14,260 --> 00:05:14,740
at the end.

82
00:05:15,580 --> 00:05:20,440
Third, this is on the 0.164 line, which is
currently in alpha releases.

83
00:05:21,020 --> 00:05:25,840
The pull request merged to main on October
20th, so confirm it's in the build you

84
00:05:25,900 --> 00:05:27,360
run before relying on it.

85
00:05:28,007 --> 00:05:30,407
A few smaller things from the last day or
two.

86
00:05:31,147 --> 00:05:33,507
Multi agent V2 now defaults

87
00:05:33,787 --> 00:05:40,567
features.multi_agent_v2.preserve_fork_prefix
to

88
00:05:40,647 --> 00:05:40,927
true.

89
00:05:41,747 --> 00:05:46,507
Full history forks keep the parent's model
visible history and append the child

90
00:05:46,567 --> 00:05:49,907
instructions after it, including for
grandchild forks.

91
00:05:50,887 --> 00:05:55,047
If you relied on instruction filtering,
set it to false explicitly.

92
00:05:56,007 --> 00:06:01,267
That default also helps the cache story,
since a preserved prefix is what makes

93
00:06:01,327 --> 00:06:02,547
forks cache friendly.

94
00:06:03,582 --> 00:06:06,882
Also, auth header construction is now
fallible.

95
00:06:07,482 --> 00:06:11,702
Before, if managed authentication became
unavailable, building headers could

96
00:06:11,762 --> 00:06:13,462
silently return no credentials.

97
00:06:14,062 --> 00:06:18,622
Now it returns an error instead of sending
a request with missing or partial auth.

98
00:06:19,242 --> 00:06:24,402
Transient MCP auth errors get retried,
while build errors and policy denials are

99
00:06:24,442 --> 00:06:24,862
terminal.

100
00:06:25,342 --> 00:06:31,582
There's a new metric,
codex.guardian.turn.blocking_ms, that measures how long

101
00:06:31,602 --> 00:06:35,222
Guardian approvals block a turn, counting
overlapping waits once.

102
00:06:35,802 --> 00:06:40,162
And a fix for a panic after background
compaction fails before a checkpoint.

103
00:06:40,742 --> 00:06:42,522
It now falls back to foreground
compaction.

104
00:06:43,367 --> 00:06:49,627
So the action item: if you run parallel
subagents, look at your request logs and see

105
00:06:49,687 --> 00:06:53,427
whether sibling workers send different
cache keys over the same prefix.

106
00:06:54,487 --> 00:06:58,107
If they do, a shared custom key is the
first thing to test,

107
00:06:58,967 --> 00:07:02,607
and then compare cache read and write
token counts before and after.

108
00:07:03,147 --> 00:07:04,287
That's what tells you if it worked.

