Hooks run custom code before or after a specific agent. Use them to prepare and clean up the page per agent.
Note
For simple page automation such as waiting or clicking cookie banners, use Knowledge Files with the wait, waitForElement, or code fields. Reach for hooks when you need different behavior for different agents.
| Use Case | Solution |
|---|---|
| Wait for element on all page visits | Knowledge: waitForElement |
| Dismiss cookie banner on page load | Knowledge: code |
| Wait for network idle only during research | Hook: researcher.beforeHook |
| Clean up test data after each test | Hook: tester.afterHook |
| Different waits for navigation vs testing | Hooks for each agent |
Hooks are configured per-agent in explorbot.config.js:
export default {
ai: {
model: myProvider('gpt-4o'),
agents: {
navigator: {
beforeHook: {
type: 'playwright',
hook: async ({ page, url }) => {
await page.waitForLoadState('networkidle');
}
}
},
tester: {
afterHook: {
type: 'codeceptjs',
hook: async ({ I, url }) => {
await I.executeScript(() => localStorage.clear());
}
}
}
}
}
}Get direct access to the Playwright page object:
beforeHook: {
type: 'playwright',
hook: async ({ page, url }) => {
await page.waitForLoadState('networkidle');
await page.locator('.loading').waitFor({ state: 'hidden' });
}
}Use the CodeceptJS I actor:
beforeHook: {
type: 'codeceptjs',
hook: async ({ I, url }) => {
await I.waitForElement('.page-ready');
await I.wait(1);
}
}Run different hooks for different URL patterns:
researcher: {
beforeHook: {
'/login': {
type: 'codeceptjs',
hook: async ({ I }) => await I.waitForElement('#login-form')
},
'/admin/*': {
type: 'playwright',
hook: async ({ page }) => await page.waitForLoadState('networkidle')
},
'/api/*': {
type: 'codeceptjs',
hook: async ({ I }) => await I.wait(2)
}
}
}| Pattern | Matches |
|---|---|
/login |
Exact path /login |
/admin/* |
/admin and any path starting with /admin/ |
* |
All URLs (fallback) |
^/users/\d+$ |
Regex: /users/ followed by digits |
**/*.html |
Glob: any .html file |
| Agent | beforeHook | afterHook | Description |
|---|---|---|---|
navigator |
After navigation | After page capture | Browser navigation |
researcher |
After navigation | After research complete | Page analysis |
tester |
Before test loop | After test loop | Test execution |
driller |
Before drilling starts | After drilling completes | Component drilling |
captain |
Before handling command | After command complete | User commands |
Warning
The planner agent does not support hooks as it doesn't interact with the browser.
navigator: {
beforeHook: {
type: 'playwright',
hook: async ({ page }) => {
await page.waitForFunction(() => {
return window.__APP_READY__ === true;
});
}
}
}researcher: {
beforeHook: {
type: 'codeceptjs',
hook: async ({ I }) => {
const modalVisible = await I.grabNumberOfVisibleElements('.modal-overlay');
if (modalVisible > 0) {
await I.click('.modal-close');
await I.wait(0.5);
}
}
}
}tester: {
afterHook: {
type: 'playwright',
hook: async ({ page }) => {
await page.evaluate(() => {
localStorage.clear();
sessionStorage.clear();
});
}
}
}tester: {
beforeHook: {
'/checkout': {
type: 'codeceptjs',
hook: async ({ I }) => {
// Ensure cart has items before checkout tests
await I.executeScript(() => {
if (!localStorage.getItem('cart')) {
localStorage.setItem('cart', JSON.stringify([{ id: 1, qty: 1 }]));
}
});
}
},
'/admin/*': {
type: 'codeceptjs',
hook: async ({ I }) => {
// Ensure admin session
await I.waitForElement('.admin-header', 5);
}
}
}
}A hook error is logged but does not stop the agent:
beforeHook: {
type: 'codeceptjs',
hook: async ({ I }) => {
try {
await I.waitForElement('.optional-banner', 2);
await I.click('.dismiss');
} catch {
// Banner not present, continue
}
}
}┌─────────────────────────────────────────────────────────┐
│ Agent Execution │
├─────────────────────────────────────────────────────────┤
│ 1. Agent starts │
│ 2. Navigate to URL (if applicable) │
│ 3. ▶ beforeHook executes │
│ 4. Agent performs main work │
│ 5. ▶ afterHook executes │
│ 6. Agent completes │
└─────────────────────────────────────────────────────────┘
- Knowledge Files — page-level automation with
wait,waitForElement,code - Configuration — full configuration reference
- Agents — agent descriptions and workflows