Skip to content
Entertainment
Skill

/adversary

Subagent orchestration for sophisticated opponent modeling and multi-party analysis.

BOOST
From plugin
palpatine
1108 skills
Install
$ npx -y skills add NovusEdge/palpatine --skill adversary --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/adversary

Context preview

The summary Claude sees to decide when to auto-load this skill.

Subagent orchestration for sophisticated opponent modeling and multi-party analysis.

SKILL.md

adversary.SKILL.md
name: adversary
description: Subagent orchestration for sophisticated opponent modeling and multi-party analysis.

Adversary Simulation

Invoked via Claude Code `/palpatine:adversary` or Codex `$palpatine:adversary`, or auto-triggered for:

  • Wargames with sophisticated opponents
  • Multi-party scenarios (3+ players)
  • Counter mode with complex stakeholder dynamics

When to Use Subagents

**Use subagents when:**

  • Multiple independent perspectives needed simultaneously
  • Opponent sophistication warrants dedicated modeling
  • User wants deep multi-party analysis

**Don't use subagents when:**

  • Single obvious opponent
  • Simple 2-party dynamics
  • Quick read is sufficient

Host Agent Patterns

Schemas

Use these schemas in the controller. Agents return raw JSON; the controller parses it, validates the exact shape, and requests one correction before treating the response as a gap.

// Single adversary response
const ADVERSARY_SCHEMA = {
  type: "object",
  properties: {
    counter: {
      type: "string",
      description: "Their response move, not reasoning"
    },
    exploits: {
      type: "array",
      items: { type: "string" },
      maxItems: 3,
      description: "Target weaknesses they'd hit"
    },
    escalation: {
      type: "string",
      description: "How they escalate if resisted"
    },
    weakPoint: {
      type: "string",
      description: "Where they're exposed"
    }
  },
  required: ["counter", "exploits", "escalation", "weakPoint"]
}

// Multi-party player analysis
const PLAYER_SCHEMA = {
  type: "object",
  properties: {
    move: { type: "string" },
    alliance: {
      type: "string",
      description: "Who they side with and why it serves them"
    },
    threat: {
      type: "string",
      description: "How they could hurt target"
    },
    price: {
      type: "string",
      description: "Cost to neutralize or buy them off"
    },
    threatLevel: {
      type: "string",
      enum: ["high", "medium", "low"]
    }
  },
  required: ["move", "alliance", "threat", "price", "threatLevel"]
}

function validateJsonObject(rawResponse, schema) {
  let response;
  try {
    response = typeof rawResponse === "string"
      ? JSON.parse(rawResponse)
      : rawResponse;
  } catch {
    return null;
  }
  if (response === null || typeof response !== "object" || Array.isArray(response)) {
    return null;
  }
  const expectedKeys = [...schema.required].sort();
  const actualKeys = Object.keys(response).sort();
  if (
    actualKeys.length !== expectedKeys.length ||
    actualKeys.some((key, index) => key !== expectedKeys[index])
  ) {
    return null;
  }
  for (const key of schema.required) {
    const definition = schema.properties[key];
    const value = response[key];
    if (definition.type === "string" && typeof value !== "string") return null;
    if (
      definition.type === "array" &&
      (!Array.isArray(value) ||
        value.some((item) => typeof item !== definition.items.type) ||
        (definition.maxItems !== undefined && value.length > definition.maxItems))
    ) {
      return null;
    }
    if (definition.enum && !definition.enum.includes(value)) return null;
  }
  return response;
}

Host Adapters

**Codex:**

  • Use `spawn_agent` with `fork_turns: "none"` and all player context in the prompt.
  • Ask for the exact keys `move`, `alliance`, `threat`, `price`, and `threatLevel`.
  • Use `list_agents` to derive current capacity, choose an unused run component, and read completed payloads keyed by the canonical task names returned from `spawn_agent`.
  • Use `wait_agent` only as a mailbox notification, `followup_task` for one correction, and `interrupt_agent` for workers still pending at the deadline. Leaf workers never spawn.
  • Inherit the orchestrator model. Forward `userRequestedModel` only when the user explicitly named a model; never infer an override.

**Claude Code:**

  • Call `Agent` with required `description` and `prompt` fields. `subagent_type` is optional. The current tool does not accept `schema`.
  • Request raw JSON in the prompt, then validate it against `PLAYER_SCHEMA` or `ADVERSARY_SCHEMA` in the controller and request one correction if needed.
  • Use `Promise.all` only for independent players.

Single Adversary

Spawn one agent for focused opponent modeling:

async function runClaudeAdversary() {
  let rawResponse = await Agent({
    description: "Adversary: [role]",
    prompt: `Model [OPPONENT] as ruthless rational actor.

OPPONENT: [role/name]
GOALS: [what they want — specific]
RESOURCES: [leverage, relationships, info, authority]
CONSTRAINTS: [what stops them from going nuclear]

TARGET is about to: [user's planned move]

Assume competent and self-interested. What's their counter-move?
Return only raw JSON with exactly these keys: counter, exploits, escalation, weakPoint.
No Markdown fences. Most likely play, stated cold.`
  });
  let response = validateJsonObject(rawResponse, ADVERSARY_SCHEMA);
  if (!response) {
    rawResponse = await Agent({
      description: "Correct adversary JSON",
      prompt: `The prior response was invalid: ${rawResponse}
Return only raw JSON with exactly these keys: counter, exploits, escalation, weakPoint.`
    });
    response = validateJsonObject(rawResponse, ADVERSARY_SCHEMA);
  }
  if (!response) throw new Error("Claude adversary returned invalid JSON after correction.");
  return response;
}

Multi-Party (Bounded Waves)

Dispatch only independent players. At most five player models run per invocation, and each wave is capped by current worker capacity:

const CODEX_TEAM_SLOT_LIMIT = 4;

function chooseUnusedRunComponent(agents, taskPrefix) {
  const existingLeafNames = agents.map((agent) => agent.agent_name.split("/").at(-1));
  for (let runIndex = 0; ; runIndex += 1) {
    const runComponent = `r${runIndex}`;
    const reservedPrefix = `${taskPrefix}_${runComponent}_`;
    if (!existingLeafNames.some((name) => name.star
Read more
Ships withpalpatine

High-functioning predator for Codex and Claude Code. No moralizing. No disclaimers. Pattern recognition without sentiment.

Get the whole plugin
Stats
110
Stars
7
Forks
Maintained
Maintenance
JavaScript
Language
1mo ago
Last commit
4mo ago
Created
1d ago
Added

Repo: NovusEdge/palpatine

Other skills on palpatine.