> For the complete documentation index, see [llms.txt](https://adaptix-framework.gitbook.io/adaptix-framework/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://adaptix-framework.gitbook.io/adaptix-framework/development/teamserver-interface/events-and-hooks.md).

# Events and Hooks

The AdaptixC2 TeamServer event system allows plugins to react to various actions in the system: agent connections, task execution, tunnel creation, etc.&#x20;

## Architecture

<figure><img src="/files/m6fhvaMT3POytyaea9SE" alt=""><figcaption></figcaption></figure>

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                           EVENT SYSTEM ARCHITECTURE                         │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌────────────────────────────────────────────────────────────────────────┐ │
│  │                         EVENT MANAGER                                  │ │
│  │                                                                        │ │
│  │   ┌─────────────────────────────────────────────────────────────────┐  │ │
│  │   │                      HOOK REGISTRY                              │  │ │
│  │   │                                                                 │  │ │
│  │   │  EventType: "agent.new"                                         │  │ │
│  │   │  ├── Hook[0]: {Name: "validator", Phase: Pre, Priority: 10}     │  │ │
│  │   │  ├── Hook[1]: {Name: "logger", Phase: Pre, Priority: 100}       │  │ │
│  │   │  ├── Hook[2]: {Name: "notifier", Phase: Post, Priority: 50}     │  │ │
│  │   │  └── Hook[3]: {Name: "analytics", Phase: Post, Priority: 100}   │  │ │
│  │   │                                                                 │  │ │
│  │   │  EventType: "task.complete"                                     │  │ │
│  │   │  ├── Hook[0]: {Name: "logger", Phase: Post, Priority: 100}      │  │ │
│  │   │  └── ...                                                        │  │ │
│  │   └─────────────────────────────────────────────────────────────────┘  │ │
│  │                                                                        │ │
│  │   ┌─────────────────────────────────────────────────────────────────┐  │ │
│  │   │                      WORKER POOL                                │  │ │
│  │   │                                                                 │  │ │
│  │   │   Worker[0] ─┬─> Process async Post hooks                       │  │ │
│  │   │   Worker[1] ─┤                                                  │  │ │
│  │   │   Worker[2] ─┤                                                  │  │ │
│  │   │   Worker[3] ─┘                                                  │  │ │
│  │   │                                                                 │  │ │
│  │   └─────────────────────────────────────────────────────────────────┘  │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  ═══════════════════════════════════════════════════════════════════════    │
│                                                                             │
│                              EVENT FLOW                                     │
│                                                                             │
│  Action Triggered                                                           │
│         │                                                                   │
│         V                                                                   │
│  ┌─────────────┐     ┌─────────────┐     ┌─────────────┐                    │
│  │  PRE HOOKS  │────>│   ACTION    │────>│ POST HOOKS  │                    │
│  │ (sync)      │     │  EXECUTED   │     │ (async)     │                    │
│  └─────────────┘     └─────────────┘     └─────────────┘                    │
│         │                                        │                          │
│         │ Can cancel                             │ Cannot cancel            │
│         │ Timeout: 5s                            │ Timeout: 30s             │
│         V                                        V                          │
│  event.Cancel(err)                        Notifications, logging, etc       │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
```

<table><thead><tr><th width="154">Concept</th><th>Description</th></tr></thead><tbody><tr><td><strong>Event</strong></td><td>Notification about an action in the system</td></tr><tr><td><strong>Hook</strong></td><td>Event handler function</td></tr><tr><td><strong>Phase</strong></td><td>Execution phase: Pre (before) or Post (after)</td></tr><tr><td><strong>Priority</strong></td><td>Execution priority (lower = earlier)</td></tr><tr><td><strong>Timeout</strong></td><td>Maximum hook execution time</td></tr></tbody></table>

## Hook **Phases**

The event system supports two hook phases with fundamentally different capabilities.

### **Pre Hooks (Phase: Pre)**

Pre hooks execute **before** the main action is performed. They have full control over the event:

<table><thead><tr><th width="144">Capability</th><th>Description</th></tr></thead><tbody><tr><td><strong>Modify data</strong></td><td>Can modify event data before the action executes. Changes are passed to subsequent hooks and the action itself</td></tr><tr><td><strong>Cancel event</strong></td><td>Can completely cancel the event by returning an error. The action will not be executed</td></tr><tr><td><strong>Validate</strong></td><td>Can validate input data and reject invalid requests</td></tr><tr><td><strong>Synchronous</strong></td><td>Execute sequentially in priority order. Block the action until all Pre hooks complete</td></tr><tr><td><strong>Timeout</strong></td><td>5 seconds maximum execution time per hook</td></tr></tbody></table>

**Use cases:**

* Input validation (reject agents from specific IP ranges)
* Data enrichment (add tags, modify parameters)
* Access control (block certain operations)
* Data transformation before processing

```go
// Example: Pre hook that can cancel the event
Ts.TsEventHookRegister("agent.new", "ip_filter", HookPre, 10, func(event any) error {
    e := event.(*adaptix.EventDataAgentNew)
    
    // Modify data
    e.AgentData.Tag = "auto-tagged"
    
    // Cancel event if condition met
    if isBlockedIP(e.AgentData.ExternalIP) {
        return fmt.Errorf("blocked IP: %s", e.AgentData.ExternalIP)
    }
    
    return nil // Allow event to proceed
})
```

### **Post Hooks (Phase: Post)**

Post hooks execute **after** the main action has completed. They are read-only observers:

<table><thead><tr><th width="169">Capability</th><th>Description</th></tr></thead><tbody><tr><td><strong>Read-only</strong></td><td>Receive a copy of the event data. Modifications have no effect on the system</td></tr><tr><td><strong>Cannot cancel</strong></td><td>The action has already been executed. Returning an error only logs a warning (exception: <code>agent.generate</code> — Post hooks can cancel generation and modify <code>FileName</code>/<code>FileContent</code>)</td></tr><tr><td><strong>Asynchronous</strong></td><td>Execute in parallel via worker pool. Do not block the main flow</td></tr><tr><td><strong>Timeout</strong></td><td>30 seconds maximum execution time per hook</td></tr></tbody></table>

**Use cases:**

* Notifications (Telegram, Slack, email)
* Logging and analytics
* External integrations
* Metrics collection

```go
// Example: Post hook for notifications (read-only)
Ts.TsEventHookRegister("agent.new", "telegram_notify", HookPost, 50, func(event any) error {
    e := event.(*adaptix.EventDataAgentNew)
    
    // Data is read-only, modifications are ignored
    message := fmt.Sprintf("New agent: %s from %s", e.AgentData.Id, e.AgentData.ExternalIP)
    sendTelegramMessage(message)
    
    return nil // Errors are logged but don't affect the system
})
```

#### Comparison Table

<table><thead><tr><th width="196">Feature</th><th width="276">Pre Hook</th><th>Post Hook</th></tr></thead><tbody><tr><td>Execution time</td><td>Before action</td><td>After action</td></tr><tr><td>Can modify data</td><td>✅ Yes</td><td>❌ No (read-only copy)</td></tr><tr><td>Can cancel event</td><td>✅ Yes (return error)</td><td>❌ No</td></tr><tr><td>Execution mode</td><td>Synchronous</td><td>Asynchronous</td></tr><tr><td>Blocks main flow</td><td>✅ Yes</td><td>❌ No</td></tr><tr><td>Timeout</td><td>5 seconds</td><td>30 seconds</td></tr><tr><td>Error handling</td><td>Cancels event</td><td>Logs warning</td></tr></tbody></table>

### Priorities

Hooks are executed in order of priority (lower value = earlier):

<table><thead><tr><th width="170">Priority</th><th>Recommended usage</th></tr></thead><tbody><tr><td>1-10</td><td>Critical validators</td></tr><tr><td>10-50</td><td>Data modifiers</td></tr><tr><td>50-100</td><td>Standard processing</td></tr><tr><td>100+</td><td>Logging, monitoring</td></tr></tbody></table>

## Event Types

### Client Events

<table><thead><tr><th width="203">Event Type</th><th width="239">Description</th><th>Data</th></tr></thead><tbody><tr><td><code>client.connect</code></td><td>Client GUI connection</td><td><code>EventDataClientConnect</code></td></tr><tr><td><code>client.disconnect</code></td><td>Client GUI disconnection</td><td><code>EventDataClientDisconnect</code></td></tr></tbody></table>

### Agent Events

<table><thead><tr><th width="175">Event Type</th><th>Description</th><th>Data</th></tr></thead><tbody><tr><td><code>agent.new</code></td><td>New agent connected</td><td><code>EventDataAgentNew</code></td></tr><tr><td><code>agent.generate</code></td><td>Agent payload generation</td><td><code>EventDataAgentGenerate</code></td></tr><tr><td><code>agent.checkin</code></td><td>Agent check-in (heartbeat)</td><td><code>EventDataAgentCheckin</code></td></tr><tr><td><code>agent.activate</code></td><td>Agent activated (from Inactive)</td><td><code>EventDataAgentActivate</code></td></tr><tr><td><code>agent.update</code></td><td>Agent data update</td><td><code>EventDataAgentUpdate</code></td></tr><tr><td><code>agent.terminate</code></td><td>Agent terminated</td><td><code>EventDataAgentTerminate</code></td></tr><tr><td><code>agent.remove</code></td><td>Agent removed</td><td><code>EventDataAgentRemove</code></td></tr></tbody></table>

### Listener Events

<table><thead><tr><th width="170">Event Type</th><th>Description</th><th>Data</th></tr></thead><tbody><tr><td><code>listener.start</code></td><td>Listener started (start/resume)</td><td><code>EventDataListenerStart</code></td></tr><tr><td><code>listener.stop</code></td><td>Listener stopped (stop/pause)</td><td><code>EventDataListenerStop</code></td></tr></tbody></table>

### Task Events

| Event Type        | Description            | Data                     |
| ----------------- | ---------------------- | ------------------------ |
| `task.create`     | Task creation          | `EventDataTaskCreate`    |
| `task.start`      | Task start             | `EventDataTaskStart`     |
| `task.update_job` | Background task update | `EventDataTaskUpdateJob` |
| `task.complete`   | Task completion        | `EventDataTaskComplete`  |

### Credentials Events

| Event Type           | Description         | Data                     |
| -------------------- | ------------------- | ------------------------ |
| `credentials.add`    | Credentials added   | `EventCredentialsAdd`    |
| `credentials.edit`   | Credentials edited  | `EventCredentialsEdit`   |
| `credentials.remove` | Credentials removed | `EventCredentialsRemove` |

### Download Events

| Event Type        | Description       | Data                      |
| ----------------- | ----------------- | ------------------------- |
| `download.start`  | Download started  | `EventDataDownloadStart`  |
| `download.finish` | Download finished | `EventDataDownloadFinish` |
| `download.remove` | Download removed  | `EventDataDownloadRemove` |

### Screenshot Events

| Event Type          | Description        | Data                        |
| ------------------- | ------------------ | --------------------------- |
| `screenshot.add`    | Screenshot added   | `EventDataScreenshotAdd`    |
| `screenshot.remove` | Screenshot removed | `EventDataScreenshotRemove` |

### Tunnel Events

| Event Type     | Description    | Data                   |
| -------------- | -------------- | ---------------------- |
| `tunnel.start` | Tunnel started | `EventDataTunnelStart` |
| `tunnel.stop`  | Tunnel stopped | `EventDataTunnelStop`  |

### Target Events

| Event Type      | Description    | Data                    |
| --------------- | -------------- | ----------------------- |
| `target.add`    | Target added   | `EventDataTargetAdd`    |
| `target.edit`   | Target edited  | `EventDataTargetEdit`   |
| `target.remove` | Target removed | `EventDataTargetRemove` |

### Pivot Events

| Event Type     | Description              | Data                   |
| -------------- | ------------------------ | ---------------------- |
| `pivot.create` | Pivot connection created | `EventDataPivotCreate` |
| `pivot.remove` | Pivot connection removed | `EventDataPivotRemove` |

***

## Hook Registration

### TsEventHookRegister

Full registration with all parameters specified.

```go
hookId := Ts.TsEventHookRegister(
    eventType string,           // Event type
    name string,                // Hook name (for identification)
    phase int,                  // 0 = Pre, 1 = Post
    priority int,               // Execution priority
    handler func(event any) error,  // Handler function
) string  // Returns a unique hook ID
```

**Example:**

```go
const (
    HookPre  = 0
    HookPost = 1
)

hookId := Ts.TsEventHookRegister("agent.new", "my_handler", HookPost, 50, 
    func(event any) error {
        data := event.(*eventing.EventDataAgentNew)
        fmt.Printf("New agent: %s\n", data.Agent.Id)
        return nil
    })
```

### TsEventHookOnPre / TsEventHookOnPost

Simplified registration for Pre/Post hooks.

```go
// Pre hook with default priority
hookId := Ts.TsEventHookOnPre("agent.new", "validator", func(event any) error {
    // ...
    return nil
})

// Post hook with default priority
hookId := Ts.TsEventHookOnPost("agent.terminate", "notifier", func(event any) error {
    // ...
    return nil
})
```

### TsEventHookUnregister

Unregister a hook by ID.

```go
success := Ts.TsEventHookUnregister(hookId) // bool
```

### TsEventHookUnregisterByName

Unregister all hooks with the specified name.

```go
count := Ts.TsEventHookUnregisterByName("my_handler") // int - number removed
```

***

## Event Data Structures

### BaseEvent

Base structure embedded in all events.

```go
type BaseEvent struct {
    Type      EventType   // Event type
    Phase     HookPhase   // Phase (Pre/Post)
    Cancelled bool        // Cancellation flag
    Error     error       // Error (if any)
}

// Method to cancel an action (Pre hooks only)
func (e *BaseEvent) Cancel(err error) {
    e.Cancelled = true
    e.Error = err
}
```

### Client Events

```go
type EventDataClientConnect struct {
    BaseEvent
    Username string   // Username
}

type EventDataClientDisconnect struct {
    BaseEvent
    Username string
}
```

### Agent Events

```go
type EventDataAgentNew struct {
    BaseEvent
    Agent   adaptix.AgentData   // Agent data
    Restore bool                // true if restored from DB
}

type EventDataAgentGenerate struct {
    BaseEvent
    BuilderId     string   // Builder ID (for logging and cancellation)
    AgentName     string   // Agent type name
    ListenersName []string // List of listeners
    Config        string   // Configuration (JSON)
    FileName      string   // File name
    FileContent   []byte   // File content
}

type EventDataAgentCheckin struct {
    BaseEvent
    Agent adaptix.AgentData
}

type EventDataAgentActivate struct {
    BaseEvent
    Agent adaptix.AgentData   // Activated agent data
}

type EventDataAgentUpdate struct {
    BaseEvent
    Agent adaptix.AgentData
}

type EventDataAgentTerminate struct {
    BaseEvent
    AgentId string   // Agent ID
    TaskId  string   // Terminate task ID
}

type EventDataAgentRemove struct {
    BaseEvent
    Agent adaptix.AgentData
}
```

### Listener Events

```go
type EventDataListenerStart struct {
    BaseEvent
    ListenerName string   // Listener name
    ListenerType string   // Listener type
    Config       string   // Configuration (JSON)
}

type EventDataListenerStop struct {
    BaseEvent
    ListenerName string   // Listener name
    ListenerType string   // Listener type
}
```

### Task Events

```go
type EventDataTaskCreate struct {
    BaseEvent
    AgentId string
    Task    adaptix.TaskData
    Cmdline string
    Client  string   // Operator name
}

type EventDataTaskStart struct {
    BaseEvent
    AgentId string
    Task    adaptix.TaskData
}

type EventDataTaskUpdateJob struct {
    BaseEvent
    AgentId string
    Task    adaptix.TaskData
}

type EventDataTaskComplete struct {
    BaseEvent
    AgentId string
    Task    adaptix.TaskData
}
```

### Credentials Events

```go
type EventCredentialsAdd struct {
    BaseEvent
    Credentials []adaptix.CredsData
}

type EventCredentialsEdit struct {
    BaseEvent
    CredId  string
    OldCred adaptix.CredsData
    NewCred adaptix.CredsData
}

type EventCredentialsRemove struct {
    BaseEvent
    CredIds []string
}
```

### Download Events

```go
type EventDataDownloadStart struct {
    BaseEvent
    AgentId  string
    FileId   string
    FileName string
    FileSize int
}

type EventDataDownloadFinish struct {
    BaseEvent
    Download adaptix.DownloadData
    Canceled bool
}

type EventDataDownloadRemove struct {
    BaseEvent
    FileIds []string
}
```

### Screenshot Events

```go
type EventDataScreenshotAdd struct {
    BaseEvent
    AgentId string
    Note    string
    Content []byte
}

type EventDataScreenshotRemove struct {
    BaseEvent
    ScreenId string
}
```

### Tunnel Events

```go
type EventDataTunnelStart struct {
    BaseEvent
    AgentId    string
    TunnelId   string
    TunnelType int
    Port       int
    Info       string
}

type EventDataTunnelStop struct {
    BaseEvent
    AgentId    string
    TunnelId   string
    TunnelType int
    Port       int
}
```

### Target Events

```go
type EventDataTargetAdd struct {
    BaseEvent
    Targets []adaptix.TargetData
}

type EventDataTargetEdit struct {
    BaseEvent
    Target adaptix.TargetData
}

type EventDataTargetRemove struct {
    BaseEvent
    TargetIds []string
}
```

### Pivot Events

```go
type EventDataPivotCreate struct {
    BaseEvent
    PivotId       string
    ParentAgentId string
    ChildAgentId  string
    PivotName     string
}

type EventDataPivotRemove struct {
    BaseEvent
    PivotId string
}
```

***

## Usage Examples

### Example 1: Event Logger

```go
package main

import (
    "fmt"
    "time"
)

const (
    HookPre  = 0
    HookPost = 1
)

var AllEventTypes = []string{
    "client.connect", "client.disconnect",
    "agent.new", "agent.activate", "agent.terminate", "agent.remove",
    "listener.start", "listener.stop",
    "task.create", "task.complete",
    "download.start", "download.finish",
    "tunnel.start", "tunnel.stop",
    "pivot.create", "pivot.remove",
}

func InitPlugin(ts any, moduleDir string, serviceConfig string) adaptix.PluginService {
    Ts = ts.(Teamserver)
    
    for _, eventType := range AllEventTypes {
        et := eventType
        
        // Pre hook
        Ts.TsEventHookRegister(et, "event_logger_pre", HookPre, 100, 
            func(event any) error {
                logEvent("PRE", et, event)
                return nil
            })
        
        // Post hook
        Ts.TsEventHookRegister(et, "event_logger_post", HookPost, 100, 
            func(event any) error {
                logEvent("POST", et, event)
                return nil
            })
    }
    
    fmt.Println("[EventLogger] All event hooks registered")
    return &PluginService{}
}

func logEvent(phase string, eventType string, event any) {
    timestamp := time.Now().Format("2006-01-02 15:04:05.000")
    fmt.Printf("[%s] [%s] %s: %+v\n", timestamp, phase, eventType, event)
}
```

### Example 2: IP Blacklist Validator (Pre Hook)

```go
package main

import (
    "errors"
    "strings"
)

const HookPre = 0

var blacklistedIPs = []string{
    "10.0.0.1",
    "192.168.1.100",
}

var blacklistedSubnets = []string{
    "172.16.",
}

func InitPlugin(ts any, moduleDir string, serviceConfig string) adaptix.PluginService {
    Ts = ts.(Teamserver)
    
    // Register Pre hook for validation
    Ts.TsEventHookRegister("agent.new", "ip_validator", HookPre, 10, 
        func(event any) error {
            data := event.(*EventDataAgentNew)
            
            // Skip restore from DB
            if data.Restore {
                return nil
            }
            
            ip := data.Agent.ExternalIP
            
            // Check exact IPs
            for _, blocked := range blacklistedIPs {
                if ip == blocked {
                    data.Cancel(errors.New("IP is blacklisted"))
                    return errors.New("blocked IP: " + ip)
                }
            }
            
            // Check subnets
            for _, subnet := range blacklistedSubnets {
                if strings.HasPrefix(ip, subnet) {
                    data.Cancel(errors.New("IP subnet is blacklisted"))
                    return errors.New("blocked subnet: " + ip)
                }
            }
            
            return nil
        })
    
    return &PluginService{}
}
```

### Example 3: Auto-Tagger

```go
package main

const HookPost = 1

func InitPlugin(ts any, moduleDir string, serviceConfig string) adaptix.PluginService {
    Ts = ts.(Teamserver)
    
    // Automatic tagging of new agents
    Ts.TsEventHookRegister("agent.new", "auto_tagger", HookPost, 50, 
        func(event any) error {
            data := event.(*EventDataAgentNew)
            agent := data.Agent
            
            var tag string
            
            // Determine tag by OS
            switch agent.Os {
            case 0: // Windows
                if agent.Elevated {
                    tag = "windows-admin"
                } else {
                    tag = "windows-user"
                }
            case 1: // Linux
                tag = "linux"
            case 2: // macOS
                tag = "macos"
            }
            
            // Additional tags by domain
            if strings.Contains(strings.ToLower(agent.Domain), "dc") {
                tag += ",domain-controller"
            }
            
            // Update tags
            if tag != "" {
                Ts.TsAgentUpdateDataPartial(agent.Id, map[string]interface{}{
                    "tags": tag,
                })
            }
            
            return nil
        })
    
    return &PluginService{}
}
```

### Example 4: Webhook Integration

```go
package main

import (
    "bytes"
    "encoding/json"
    "net/http"
    "time"
)

const HookPost = 1

var webhookURL = "https://example.com/webhook"

type WebhookPayload struct {
    EventType string      `json:"event_type"`
    Timestamp int64       `json:"timestamp"`
    Data      interface{} `json:"data"`
}

func InitPlugin(ts any, moduleDir string, serviceConfig string) adaptix.PluginService {
    Ts = ts.(Teamserver)
    
    events := []string{"agent.new", "agent.terminate", "task.complete"}
    
    for _, et := range events {
        eventType := et
        Ts.TsEventHookRegister(eventType, "webhook", HookPost, 50, 
            func(event any) error {
                go sendWebhook(eventType, event)
                return nil
            })
    }
    
    return &PluginService{}
}

func sendWebhook(eventType string, event any) {
    payload := WebhookPayload{
        EventType: eventType,
        Timestamp: time.Now().Unix(),
        Data:      event,
    }
    
    jsonData, err := json.Marshal(payload)
    if err != nil {
        return
    }
    
    client := &http.Client{Timeout: 10 * time.Second}
    req, _ := http.NewRequest("POST", webhookURL, bytes.NewBuffer(jsonData))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("X-Webhook-Event", eventType)
    
    resp, err := client.Do(req)
    if err != nil {
        return
    }
    defer resp.Body.Close()
}
```

***

## Best Practices

### 1. Error Handling

```go
Ts.TsEventHookRegister("agent.new", "my_hook", HookPost, 50, 
    func(event any) error {
        // Safe type assertion
        data, ok := event.(*EventDataAgentNew)
        if !ok {
            return errors.New("invalid event type")
        }
        
        // Recover from panic
        defer func() {
            if r := recover(); r != nil {
                fmt.Printf("Hook panic recovered: %v\n", r)
            }
        }()
        
        // ... main logic ...
        
        return nil
    })
```

### 2. Asynchronous Processing in Post Hooks

```go
Ts.TsEventHookRegister("agent.new", "notifier", HookPost, 50, 
    func(event any) error {
        data := event.(*EventDataAgentNew)
        
        // Async send — do not block the event
        go func() {
            sendNotification(data.Agent)
        }()
        
        return nil  // Return nil immediately
    })
```

### 3. Correct Usage of Pre Hooks

```go
// Correct: validation and cancellation
Ts.TsEventHookRegister("agent.new", "validator", HookPre, 10, 
    func(event any) error {
        data := event.(*EventDataAgentNew)
        
        if !isAllowed(data.Agent.ExternalIP) {
            data.Cancel(errors.New("not allowed"))
            return errors.New("blocked")
        }
        
        return nil
    })

// Incorrect: long-running operations in Pre hook
Ts.TsEventHookRegister("agent.new", "slow_hook", HookPre, 10, 
    func(event any) error {
        time.Sleep(10 * time.Second)  // Blocks everything for 10 seconds!
        return nil
    })
```

### 4. Unique Hook Names

```go
// Use unique names to allow unregistration
hookId := Ts.TsEventHookRegister("agent.new", "my_service_agent_hook", ...)

// Later you can remove all service hooks
Ts.TsEventHookUnregisterByName("my_service_agent_hook")
```

### 5. Priorities

```go
// Validators — low priority (executed first)
Ts.TsEventHookRegister("agent.new", "validator", HookPre, 10, ...)

// Modifiers — medium priority
Ts.TsEventHookRegister("agent.new", "modifier", HookPre, 50, ...)

// Loggers — high priority (executed last)
Ts.TsEventHookRegister("agent.new", "logger", HookPre, 100, ...)
```

### 6. Timeouts

* Pre hooks: 5 seconds (short operations)
* Post hooks: executed in a separate thread, 30 seconds (you can do external requests)

If a hook exceeds the timeout, it is interrupted with an error.

***

### Constants

```go
// Execution phases
const (
    HookPre  = 0   // Before action (sync)
    HookPost = 1   // After action (async)
)

// Default timeouts
const (
    DefaultPreHookTimeout  = 5 * time.Second
    DefaultPostHookTimeout = 30 * time.Second
)
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://adaptix-framework.gitbook.io/adaptix-framework/development/teamserver-interface/events-and-hooks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
