You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
5.6 KiB
166 lines
5.6 KiB
#!/bin/bash |
|
############################################################################### |
|
# OpenClaw Agent Offboarding / Removal Script |
|
# |
|
# Cleanly removes an agent: stops service, removes from agents.yaml, |
|
# project_registry.yaml, optionally deletes workspace, profile, and Qdrant data. |
|
# |
|
# Usage: |
|
# ./offboard.sh <agent_id> [--keep-data] |
|
# |
|
# Options: |
|
# --keep-data Keep workspace and profile directories (only unregister) |
|
# |
|
# Examples: |
|
# ./offboard.sh crypto # full removal |
|
# ./offboard.sh crypto --keep-data # keep files, just unregister |
|
############################################################################### |
|
|
|
set -e |
|
|
|
WORKSPACE="/root/.openclaw/workspace" |
|
AGENTS_YAML="$WORKSPACE/agents.yaml" |
|
REGISTRY="$WORKSPACE/skills/mem0-integration/project_registry.yaml" |
|
PARSE_AGENTS="python3 $WORKSPACE/scripts/parse_agents.py" |
|
|
|
RED='\033[0;31m' |
|
GREEN='\033[0;32m' |
|
YELLOW='\033[1;33m' |
|
BLUE='\033[0;34m' |
|
NC='\033[0m' |
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } |
|
log_success() { echo -e "${GREEN}[OK]${NC} $1"; } |
|
log_warning() { echo -e "${YELLOW}[WARN]${NC} $1"; } |
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; } |
|
|
|
setup_user_env() { |
|
export XDG_RUNTIME_DIR=/run/user/$(id -u) |
|
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus" |
|
} |
|
|
|
if [ $# -lt 1 ]; then |
|
echo "Usage: $0 <agent_id> [--keep-data]" |
|
exit 1 |
|
fi |
|
|
|
AGENT_ID="$1" |
|
KEEP_DATA=false |
|
[ "$2" = "--keep-data" ] && KEEP_DATA=true |
|
|
|
if [ "$AGENT_ID" = "main" ]; then |
|
log_error "Cannot remove the main (hub) agent" |
|
exit 1 |
|
fi |
|
|
|
# Validate agent exists |
|
if ! $PARSE_AGENTS info "$AGENT_ID" >/dev/null 2>&1; then |
|
log_error "Agent '${AGENT_ID}' not found in agents.yaml" |
|
exit 1 |
|
fi |
|
|
|
# Load agent info |
|
eval $($PARSE_AGENTS info "$AGENT_ID") |
|
log_info "Offboarding: ${AGENT_NAME} (${AGENT_ID}), type: ${AGENT_TYPE}" |
|
|
|
echo "" |
|
log_warning "This will remove agent '${AGENT_ID}' from the system." |
|
if [ "$KEEP_DATA" = "true" ]; then |
|
log_info "Mode: keep data (unregister only)" |
|
else |
|
log_warning "Mode: FULL removal (workspace, profile, Qdrant data will be DELETED)" |
|
fi |
|
read -p "Continue? (y/N): " confirm |
|
if [[ ! $confirm =~ ^[Yy]$ ]]; then |
|
log_info "Cancelled." |
|
exit 0 |
|
fi |
|
|
|
# 1. Stop and disable the service |
|
setup_user_env |
|
if [ "$AGENT_TYPE" = "local-systemd" ] && [ -n "$SYSTEMD_UNIT" ]; then |
|
log_info "Stopping service: $SYSTEMD_UNIT" |
|
systemctl --user stop "$SYSTEMD_UNIT" 2>/dev/null || true |
|
systemctl --user disable "$SYSTEMD_UNIT" 2>/dev/null || true |
|
rm -f "$HOME/.config/systemd/user/$SYSTEMD_UNIT" |
|
systemctl --user daemon-reload 2>/dev/null |
|
log_success "Service stopped and removed" |
|
fi |
|
|
|
# 2. Remove from agents.yaml |
|
python3 - "$AGENTS_YAML" "$AGENT_ID" <<'PYEOF' |
|
import sys, yaml |
|
yaml_path, aid = sys.argv[1:3] |
|
with open(yaml_path, 'r', encoding='utf-8') as f: |
|
data = yaml.safe_load(f) |
|
if aid in data.get('agents', {}): |
|
del data['agents'][aid] |
|
with open(yaml_path, 'w', encoding='utf-8') as f: |
|
yaml.dump(data, f, default_flow_style=False, allow_unicode=True, sort_keys=False) |
|
print('removed from agents.yaml') |
|
else: |
|
print('not found in agents.yaml') |
|
PYEOF |
|
log_success "Removed from agents.yaml" |
|
|
|
# 3. Remove from project_registry.yaml |
|
if grep -q "\"${AGENT_ID}\"" "$REGISTRY" 2>/dev/null; then |
|
sed -i "/\"${AGENT_ID}\"/d" "$REGISTRY" |
|
log_success "Removed from project_registry.yaml" |
|
else |
|
log_info "Not found in project_registry.yaml (skip)" |
|
fi |
|
|
|
# 4. Delete files (unless --keep-data) |
|
if [ "$KEEP_DATA" = "false" ]; then |
|
AGENT_WORKSPACE="$WORKSPACE/agents/${AGENT_ID}-workspace" |
|
AGENT_CONFIG_DIR="/root/.openclaw-${AGENT_ID}" |
|
SVC_FILE="$WORKSPACE/systemd/openclaw-gateway-${AGENT_ID}.service" |
|
ENV_FILE="$WORKSPACE/systemd/${AGENT_ID}-gateway.env" |
|
LOGS_DIR="$WORKSPACE/logs/agents/${AGENT_ID}" |
|
RUNTIME_DIR="/root/.openclaw/agents/${AGENT_ID}" |
|
|
|
[ -d "$AGENT_WORKSPACE" ] && rm -rf "$AGENT_WORKSPACE" && log_success "Deleted workspace: $AGENT_WORKSPACE" |
|
[ -d "$AGENT_CONFIG_DIR" ] && rm -rf "$AGENT_CONFIG_DIR" && log_success "Deleted profile: $AGENT_CONFIG_DIR" |
|
[ -f "$SVC_FILE" ] && rm -f "$SVC_FILE" && log_success "Deleted service file" |
|
[ -f "$ENV_FILE" ] && rm -f "$ENV_FILE" && log_success "Deleted env file" |
|
[ -d "$LOGS_DIR" ] && rm -rf "$LOGS_DIR" && log_success "Deleted logs" |
|
[ -d "$RUNTIME_DIR" ] && rm -rf "$RUNTIME_DIR" && log_success "Deleted runtime data" |
|
|
|
# 5. Clean Qdrant data |
|
log_info "Cleaning Qdrant memories for agent_id=${AGENT_ID}..." |
|
python3 -c " |
|
try: |
|
from qdrant_client import QdrantClient |
|
from qdrant_client.models import Filter, FieldCondition, MatchValue, FilterSelector |
|
client = QdrantClient(host='localhost', port=6333) |
|
result = client.delete( |
|
collection_name='mem0_v4_shared', |
|
points_selector=FilterSelector(filter=Filter(must=[ |
|
FieldCondition(key='agent_id', match=MatchValue(value='${AGENT_ID}')) |
|
])) |
|
) |
|
print(f'Deleted Qdrant memories: {result.status}') |
|
except Exception as e: |
|
print(f'Qdrant cleanup skipped: {e}') |
|
" 2>/dev/null |
|
log_success "Qdrant memories cleaned" |
|
fi |
|
|
|
# 6. Reload monitor |
|
systemctl restart openclaw-agent-monitor 2>/dev/null && log_success "Monitor reloaded" || log_warning "Monitor reload failed" |
|
|
|
echo "" |
|
log_success "Agent '${AGENT_ID}' has been fully removed." |
|
echo "" |
|
log_info "Summary:" |
|
echo " - Service: removed" |
|
echo " - agents.yaml: removed" |
|
echo " - project_registry: removed" |
|
if [ "$KEEP_DATA" = "false" ]; then |
|
echo " - Workspace + profile: deleted" |
|
echo " - Qdrant memories: deleted" |
|
else |
|
echo " - Workspace + profile: kept (--keep-data)" |
|
echo " - Qdrant memories: kept (--keep-data)" |
|
fi
|
|
|