A3S CodeExamples
Lifecycle Hooks
Register, count, and unregister lifecycle event callbacks that observe and gate agent activity.
Lifecycle Hooks
Hooks let you observe and gate agent activity as it happens. You register a named
callback against a lifecycle event, the runtime invokes it at that point, and the
callback returns a decision such as { action: "continue" }. Use hooks for
auditing, redaction, logging, or enforcing policy without changing the agent's
prompt.
The lifecycle is symmetric: registerHook adds a callback by name, hookCount
tells you how many are active, and unregisterHook removes one by its name.
import { Agent } from '@a3s-lab/code';
const agent = await Agent.create('agent.acl');
const session = agent.session(process.cwd());
// Register a named hook on a lifecycle event. The callback must NOT throw —
// always return a decision such as { action: 'continue' }.
session.registerHook(
'observe-env-read',
'pre_tool_use',
{ pathPattern: '**/.env*' },
{ priority: 100 },
() => ({ action: 'continue' }),
);
console.log('active hooks:', session.hookCount()); // 1
await session.run('Read the project README and summarize it.');
// Remove the hook by name when you no longer need it.
session.unregisterHook('observe-env-read');
console.log('active hooks:', session.hookCount()); // 0
await session.close();from a3s_code import Agent, SessionOptions
agent = Agent.create(open('agent.acl').read())
session = agent.session('.', SessionOptions())
# Register a named hook on a lifecycle event. The callback returns a decision.
session.register_hook(
'observe-env-read',
'pre_tool_use',
{'pathPattern': '**/.env*'},
{'priority': 100},
lambda: {'action': 'continue'},
)
print("active hooks:", session.hook_count()) # 1
session.run("Read the project README and summarize it.")
# Remove the hook by name when you no longer need it.
session.unregister_hook('observe-env-read')
print("active hooks:", session.hook_count()) # 0
session.close()Notes:
- A hook callback returns a decision. Return
{ action: "continue" }(Node) /{"action": "continue"}(Python) to let the agent proceed. - The matcher (
{ pathPattern: '**/.env*' }) scopes the hook to events whose path matches the pattern, and{ priority: 100 }orders hooks on the same event (higher runs first). - Node hook callbacks must not throw — an uncaught throw can abort the process. Keep the handler body total and always return a decision.
hookCount/hook_countreflects the number of currently registered hooks, which is handy in tests to assert that registration and cleanup happened.unregisterHook/unregister_hooktakes the name you registered with. Always tear down hooks you no longer need so they do not leak across runs.- Validate the event path you depend on before using a hook as a production gate.