1
00:00:00,320 --> 00:00:04,880
Right, grab a coffee, because today's one
is about what happens when your safety

2
00:00:05,000 --> 00:00:06,160
check falls over.

3
00:00:06,900 --> 00:00:11,620
This is The Claude Code Changelog, brought
to you by Jellypod AI.

4
00:00:12,520 --> 00:00:19,040
Version 2.1.317 landed on November 3rd,
2026, with 87

5
00:00:19,100 --> 00:00:22,500
changes across security, hooks, and
session orchestration.

6
00:00:23,240 --> 00:00:27,260
We're picking one of them, and it closes a
gap that could bite anyone running agents

7
00:00:27,440 --> 00:00:28,000
unattended.

8
00:00:28,867 --> 00:00:29,007
Yeah.

9
00:00:29,607 --> 00:00:35,767
Back in version 2.1.295 we covered
onFailure block for JSON configured command and

10
00:00:35,927 --> 00:00:36,787
HTTP hooks.

11
00:00:37,347 --> 00:00:39,167
That made those hooks fail closed.

12
00:00:39,747 --> 00:00:43,947
But Agent SDK hook callbacks, the
programmatic ones you write in code,

13
00:00:44,307 --> 00:00:44,887
were left out.

14
00:00:45,407 --> 00:00:47,587
Until now they failed open by default.

15
00:00:48,107 --> 00:00:52,107
So if your callback crashed, timed out, or
threw an unhandled error while checking a

16
00:00:52,147 --> 00:00:56,307
permission or verifying a tool call,
Claude Code let the tool run anyway.

17
00:00:57,017 --> 00:01:00,857
Which is a bit like a bouncer who falls
asleep and the club just opens the doors.

18
00:01:01,957 --> 00:01:06,477
If you're building automated agents or
headless wrappers on the Agent SDK,

19
00:01:06,997 --> 00:01:09,317
your guardrail was only as good as its
uptime.

20
00:01:10,017 --> 00:01:14,177
A flaky network call inside your callback,
a null you didn't expect,

21
00:01:14,657 --> 00:01:18,797
and a potentially destructive action slips
through without anyone saying yes.

22
00:01:19,522 --> 00:01:20,462
So here's the fix.

23
00:01:21,082 --> 00:01:25,662
In 2.1.317, when you configure a hook
handler programmatically,

24
00:01:26,022 --> 00:01:32,002
say a PreToolUse or PermissionRequest
callback, you explicitly supply onFailure set

25
00:01:32,042 --> 00:01:34,842
to block in the hook callback's
configuration options.

26
00:01:35,502 --> 00:01:39,342
Once that's on, any thrown error or failed
callback halts the tool call,

27
00:01:39,802 --> 00:01:43,282
and a blocking error is surfaced back to
the model instead of the tool proceeding.

28
00:01:43,982 --> 00:01:47,662
I'd check the SDK reference for exactly
where that option sits in your language's

29
00:01:47,702 --> 00:01:50,862
types, but the value is block, and you set
it per hook.

30
00:01:51,610 --> 00:01:52,450
Practical example.

31
00:01:53,210 --> 00:01:58,550
Say your PreToolUse callback looks up a
policy service before letting Bash commands

32
00:01:58,590 --> 00:01:58,870
through.

33
00:01:59,510 --> 00:02:03,930
Before, if that service timed out, the
callback failed, and the command ran.

34
00:02:04,590 --> 00:02:09,749
With onFailure block, the same timeout
stops the command, and the model gets told it

35
00:02:09,790 --> 00:02:10,290
was blocked.

36
00:02:10,790 --> 00:02:13,890
It can then explain, retry, or pick a
safer route.

37
00:02:14,650 --> 00:02:19,150
That's what you want from a guardrail,
deny by default when you can't confirm.

38
00:02:19,890 --> 00:02:20,830
Now, the caveats.

39
00:02:21,250 --> 00:02:24,150
First, only use this on events that can
actually block.

40
00:02:24,610 --> 00:02:29,030
The brief names PreToolUse,
PermissionRequest, UserPromptSubmit,

41
00:02:29,310 --> 00:02:30,310
and PreCompact.

42
00:02:30,850 --> 00:02:34,930
If you set it on a post execution hook
like PostToolUse, it does nothing,

43
00:02:35,310 --> 00:02:36,570
because the action already happened.

44
00:02:37,310 --> 00:02:38,570
Second, watch your timeouts.

45
00:02:39,090 --> 00:02:43,070
A blocking callback that hangs will hold
up session progress until it finally fails,

46
00:02:43,610 --> 00:02:46,490
so set reasonable limits on anything that
calls out over the network.

47
00:02:47,150 --> 00:02:48,870
And third one's for the CI crowd.

48
00:02:49,390 --> 00:02:54,950
In a headless pipeline or automated
runner, a blocking failure will abort the turn

49
00:02:55,350 --> 00:02:58,850
unless your agent is set up to catch and
recover from the denial.

50
00:02:59,570 --> 00:03:02,290
So test the unhappy path on purpose.

51
00:03:02,850 --> 00:03:07,490
Break your callback, see what the run
does, and make sure that's the outcome you

52
00:03:07,550 --> 00:03:08,910
wanted at three in the morning.

53
00:03:10,058 --> 00:03:12,238
Okay, a few smaller things from the same
release.

54
00:03:12,978 --> 00:03:14,518
One is a security one.

55
00:03:14,958 --> 00:03:19,438
There's now an interactive confirmation
when a web tool, so WebFetch,

56
00:03:19,678 --> 00:03:24,578
WebSearch, or WebBrowser, or a shell tool,
so Bash, Monitor,

57
00:03:24,918 --> 00:03:30,098
PowerShell, or Tmux, is about to send your
signed in account email address over the

58
00:03:30,138 --> 00:03:30,618
network.

59
00:03:31,258 --> 00:03:34,998
It matches both the raw string and the URL
encoded version,

60
00:03:35,438 --> 00:03:37,118
so it stops silent leakage.

61
00:03:38,175 --> 00:03:40,595
Next, nested headless sessions.

62
00:03:41,195 --> 00:03:46,735
By default, when you run claude with the p
flag inside a cloud or self hosted runner

63
00:03:46,795 --> 00:03:50,975
session, it now gets its own session ID
and its own transcript,

64
00:03:51,355 --> 00:03:53,835
instead of sharing and overwriting the
parent's.

65
00:03:54,495 --> 00:03:57,795
If you actually depended on the old shared
transcript behavior,

66
00:03:58,275 --> 00:04:03,795
set CLAUDE_CODE_DISABLE_NESTED_SESSION_ID
to 1 on your self hosted runners.

67
00:04:04,975 --> 00:04:10,375
Also, the old file unchanged since your
last Read stub is gone.

68
00:04:10,975 --> 00:04:14,335
Reading an unchanged file again now
returns the full text.

69
00:04:14,835 --> 00:04:19,295
That's more accurate, but you may see
slightly higher token use on repeat reads.

70
00:04:20,114 --> 00:04:25,375
And subagents or teammates assigned a
different model from the main conversation now

71
00:04:25,475 --> 00:04:30,095
use that model's saved effort level, or
its default, instead of inheriting the

72
00:04:30,175 --> 00:04:31,255
parent session's effort.

73
00:04:31,820 --> 00:04:33,040
One for admins too.

74
00:04:33,540 --> 00:04:38,600
The Claude apps gateway admin API has a
new GET endpoint at

75
00:04:38,620 --> 00:04:45,460
/v1/organizations/analytics/cost, which
aggregates spend across date

76
00:04:45,520 --> 00:04:48,080
ranges, developers, and IdP groups.

77
00:04:49,052 --> 00:04:50,492
So the action item is simple.

78
00:04:50,932 --> 00:04:56,432
Audit your Agent SDK code for blocking
hook callbacks, add onFailure block to the

79
00:04:56,512 --> 00:05:00,772
ones that guard anything destructive, then
deliberately make one fail and watch what

80
00:05:00,812 --> 00:05:01,212
happens.

81
00:05:01,832 --> 00:05:05,132
That's the whole job, and it's worth doing
before your next unattended run.

