Claude-Agent
view release on metacpan or search on metacpan
examples/13-async-hook.pl view on Meta::CPAN
#!/usr/bin/env perl
#
# Async Hooks Example
#
# This example demonstrates how to use asynchronous Perl hook callbacks
# for operations that require I/O, such as:
# - HTTP requests to external validation services
# - Database lookups for permission checks
# - Async logging or metrics collection
#
# Hooks can return either:
# - A hashref (synchronous, backward compatible)
# - A Future that resolves to a hashref (asynchronous)
#
use 5.020;
use strict;
use warnings;
use lib 'lib';
use Claude::Agent qw(query);
use Claude::Agent::Options;
use Claude::Agent::Hook::Matcher;
use Claude::Agent::Hook::Result;
use Future;
# Simulated async permission service
# In a real app, this might call an HTTP API or query a database
sub check_permission_async {
my ($loop, $tool_name, $user_id) = @_;
# Simulate async latency
return $loop->delay_future(after => 0.1)->then(sub {
# Simulate permission logic
my $allowed = $tool_name ne 'Bash'; # Block Bash for demo
return Future->done({
allowed => $allowed,
reason => $allowed ? 'Permission granted' : 'Bash commands require approval',
});
});
}
# Simulated async audit logging
sub log_tool_use_async {
my ($loop, $tool_name, $tool_input) = @_;
return $loop->delay_future(after => 0.05)->then(sub {
# In a real app, this might write to a database or send to a log service
my $timestamp = localtime();
say " [AUDIT $timestamp] Tool: $tool_name";
return Future->done(1);
});
}
# Define async PreToolUse hooks
my $pre_tool_hooks = [
# Async permission check hook
Claude::Agent::Hook::Matcher->new(
hooks => [sub {
my ($input, $tool_use_id, $context, $loop) = @_;
my $tool_name = $input->{tool_name};
# If we have a loop, use async permission check
if ($loop) {
say "[HOOK] Checking permissions asynchronously for: $tool_name";
( run in 1.155 second using v1.01-cache-2.11-cpan-140bd7fdf52 )