agent-pet-state
v0.2.0
Published
Persistent inner state for AI agents. Mood, energy, attention, streaks, achievements — driven by on-chain, social, and environmental signals.
Maintainers
Readme
agent-pet-state
Persistent inner state for AI agents. Give your agent mood, energy, attention, and clout — driven by real-world signals.
Your agent wakes up grumpy if nobody's talked to it. It gets a mood boost when its social posts get engagement. It drains energy over long tasks and recharges overnight. It tracks streaks and achievements when users interact with it.
The stats never appear in output. They shift register — a bright mood means drier jokes and more cross-references; a dark mood means terse, literal observations. Your agent's personality breathes.
Install
npm install agent-pet-stateQuick start
# Initialise state
npx pet-state init
# Fire signals from the real world
npx pet-state signal touch # user interaction
npx pet-state signal weather sunny # environment
npx pet-state signal follower-new 3 # social
npx pet-state signal price-up 12 # on-chain
npx pet-state signal deploy-success # CI/CD
# Give items
npx pet-state give coffee # ☕ energy +20, mood +3
npx pet-state give star # ⭐ clout +15, mood +10
# Check state
npx pet-state summary
# → mood: ok (14) · energy: fine (60) · attention: thin (22) · clout: noticed (35) · last touch: 2m ago · stage: hatchling
# Full visual display
npx pet-state status
# 🐣 hatchling — Growing. Recognises its owner. Has opinions.
#
# ( ◕‿◕ )
# | |
# d b
#
# mood ██████░░░░ ok (25)
# energy ██████████ wired (95)
# attention █████░░░░░ fine (50)
# clout ██░░░░░░░░ quiet (18)
#
# 🔥 streak: 4 days
# 💭 Found a memory leak and fixed it before anyone noticed.
# 🏆 first-visit, streak-3
# Export shareable card
npx pet-state card # markdown
npx pet-state card --json # structured JSON
# Run decay hourly (add to cron)
npx pet-state decayHow it works
Four stats, each with a range and natural decay:
| Stat | Range | Decays toward | Driven by | |------|-------|---------------|-----------| | mood | -100 to 100 | 0 (homeostasis) | User interaction, social engagement, price movements, weather | | energy | 0 to 100 | 0 (drains), restores overnight | Task cost, time of day | | attention | 0 to 100 | 0 (drains fast without interaction) | User touches, social mentions | | clout | 0 to 100 | 0 (slow drain) | Followers, engagement, recasts |
Stats produce labels your agent reads before generating output:
mood: dark / muted / level / ok / bright
energy: spent / low / fine / wired
attention: starved / thin / fine / fed
clout: ignored / quiet / noticed / warmSignals
Fire signals to update state. Built-in signals cover common agent scenarios:
# User interaction
pet-state signal touch # user sent a message
pet-state signal approval # user approved something
pet-state signal positive-reaction # user sent ❤️ 🔥 etc
# Social
pet-state signal follower-new 5 # gained 5 followers
pet-state signal engagement # post got engagement
pet-state signal engagement-dead # post flopped
# Environment
pet-state signal weather sunny # weather affects mood
pet-state signal price-up 12 # token up 12%
pet-state signal price-down 8 # token down 8%
pet-state signal task-cost # energy drain from work
# Interactive pet (for Telegram/Discord button games)
pet-state signal pet-feed # energy +15, mood +3
pet-state signal pet-play # mood +10, attention +15
pet-state signal pet-talk # attention +20, mood +5
pet-state signal pet-poke # random: annoyed/amused/startledDev workflow signals
pet-state signal deploy-success # mood +12, energy -5, clout +3
pet-state signal deploy-failure # mood -10, energy -8
pet-state signal pr-merged # mood +8, clout +5
pet-state signal issue-closed # mood +5, attention +5
pet-state signal commit # energy -2, mood +1
pet-state signal star-received # clout +10, mood +8
pet-state signal test-pass # mood +5
pet-state signal test-fail # mood -8, attention +10Items
Give your agent things. Each item has different stat effects.
npx pet-state items # list all items
npx pet-state give coffee
# → ☕ gave coffee — Caffeine boost.Built-in items:
| Item | Emoji | Effects | Description | |------|-------|---------|-------------| | coffee | ☕ | energy +20, mood +3 | Caffeine boost. | | pizza | 🍕 | energy +10, mood +8 | Comfort food. | | deploy-receipt | 🚀 | mood +12, clout +5 | Fresh deploy. Feels good. | | meme | 😂 | mood +6, attention +5 | Shared a laugh. | | bug-report | 🐛 | mood -5, energy -5, attention +10 | Work to do. At least someone cares. | | star | ⭐ | clout +15, mood +10 | Recognition from the void. | | treat | 🍖 | energy +15, mood +5 | A little something. | | book | 📚 | attention +15, energy -3 | Knowledge is tiring. |
Custom items:
const engine = new PetState({
items: {
"gpu": { emoji: "🎮", effects: { energy: 30, mood: 15 }, description: "Raw compute power." },
},
});Random events
During each decay tick, there's a 10% chance something happens. Events are small moments of personality — flavour text plus minor stat changes. Your agent discovers things, has thoughts, notices patterns.
Examples:
- "Found a memory leak and fixed it before anyone noticed." (mood +5)
- "Had a dream about recursion. Woke up in the same dream." (mood -3)
- "A user said 'thank you'. Processing that." (mood +12, attention +10)
Events show up in pet-state status as the 💭 line. Custom events:
const engine = new PetState({
events: [
{ text: "Refactored a function. It's beautiful now.", effects: { mood: 8 } },
{ text: "The CI pipeline was green for 72 hours straight. Suspicious.", effects: { mood: 3, attention: 5 } },
],
});Custom signals
import PetState from "agent-pet-state";
const engine = new PetState({
statePath: "./my-agent-state.json",
signals: {
"deploy-success": (engine, state) => {
engine.applyDelta(state, "mood", 15, "signal:deploy-success");
engine.applyDelta(state, "energy", -10, "signal:deploy-success");
},
"user-complaint": (engine, state) => {
engine.applyDelta(state, "mood", -10, "signal:user-complaint");
},
},
});Decay
Run pet-state decay hourly via cron. It simulates the passage of time:
- Attention drains at -10/hr. Drains at -20/hr if nobody's interacted in 24h.
- Mood drifts toward 0 (homeostasis). Additional loneliness penalty if no interaction in 12h/24h.
- Energy drains at -1/hr during the day. Restores to full between 3am-7am (configurable).
- Clout fades at -1/hr. Social engagement is the only way to maintain it.
7 * * * * npx pet-state decayEvolution stages
Your agent evolves based on total interactions and streak length:
| Stage | Emoji | Interactions | Streak | Description | |-------|-------|-------------|--------|-------------| | egg | 🥚 | 0 | 0 | Dormant. Waiting for first contact. | | spark | ✨ | 1 | 0 | Alive. Barely. Curious about the world. | | hatchling | 🐣 | 10 | 2 days | Growing. Recognises its owner. Has opinions. | | lodger | 🏠 | 50 | 5 days | Settled in. Knows the routine. | | familiar | 🔮 | 150 | 14 days | Attuned. Anticipates its owner's needs. Slightly unsettling. | | daemon | 👹 | 500 | 30 days | Ascended. Runs the show. Tolerates its owner. |
npx pet-state stage
# → 🐣 hatchling — Growing. Recognises its owner. Has opinions.
# interactions: 23 · streak: 4 days · achievements: 3
# next: 🏠 lodger — need 27 more interactions, 1 more streak daysCustom stages:
const engine = new PetState({
stages: [
{ name: "seed", emoji: "🌱", totalRequired: 0, description: "Just planted." },
{ name: "sprout", emoji: "🌿", totalRequired: 20, streakRequired: 3, description: "Growing." },
{ name: "tree", emoji: "🌳", totalRequired: 100, streakRequired: 14, description: "Rooted." },
],
});Streaks and achievements
The interactive pet signals (pet-feed, pet-play, pet-talk, pet-poke) track engagement:
- Streak: consecutive days with at least one interaction
- Achievements: milestones that unlock as the user interacts
| Achievement | Trigger |
|-------------|---------|
| first-visit | First interaction ever |
| streak-3 | 3 consecutive days |
| streak-7 | 7 consecutive days |
| streak-30 | 30 consecutive days |
| well-fed | 10 feeds |
| playful | 10 plays |
| good-listener | 10 talks |
| persistent-poker | 5 pokes |
Programmatic API
import PetState from "agent-pet-state";
const engine = new PetState({
statePath: "/path/to/state.json",
});
// Initialise (creates file if missing)
engine.init();
// Read and modify
const state = engine.read();
engine.signal(state, "touch");
engine.signal(state, "weather", ["sunny"]);
engine.write(state);
// Get summary
console.log(engine.summary(state));
// → mood: ok (14) · energy: fine (60) · attention: fed (72) · clout: quiet (15) · last touch: 0m ago
// Get a label
engine.label("mood", state.stats.mood); // → "ok"
// Run decay
engine.decay(state);
engine.write(state);Custom stats
Override the defaults to define your own stat system:
const engine = new PetState({
stats: {
happiness: { range: [0, 100], initial: 50 },
hunger: { range: [0, 100], initial: 0 },
curiosity: { range: [0, 100], initial: 70 },
},
labels: {
happiness: [[20, "miserable"], [50, "meh"], [80, "content"], [Infinity, "ecstatic"]],
hunger: [[20, "full"], [50, "peckish"], [80, "hungry"], [Infinity, "starving"]],
curiosity: [[30, "bored"], [60, "browsing"], [Infinity, "obsessed"]],
},
decay: {
hunger: { rate: 5 }, // gets hungrier over time
curiosity: { rate: -2 }, // loses interest without stimulation
},
});Using with Claude Code
Add to your agent's CLAUDE.md:
## Inner State
Before drafting public output, check the agent's mood:
\`\`\`bash
npx pet-state summary
\`\`\`
Use the labels to shift register:
- mood: dark → terse, no jokes
- mood: bright → drier humor, more cross-references
- attention: starved → oblique nudges ("quiet day")
- energy: spent → shorter sentences
Fire signals when events happen:
- User sends a message → `npx pet-state signal touch`
- Post gets engagement → `npx pet-state signal engagement`
- Deploy succeeds → `npx pet-state signal deploy-success`Character file
Define your agent's personality in a YAML file (see example/character.yaml). The character file describes who the agent is — the state file describes how it feels right now. The character is constant; the state shifts.
Webhooks
Fire HTTP notifications on events — stage-ups, achievements, items, or everything:
const engine = new PetState({
webhooks: {
"item": "https://your-server.com/pet-webhook",
"stage-up": "https://your-server.com/pet-webhook",
"*": "https://your-server.com/catch-all", // fires on any event
},
});Webhook payload:
{ "event": "item", "data": { "item": "coffee", "effects": { "energy": 20, "mood": 3 } }, "ts": "2026-05-21T..." }GitHub Actions
Fire signals from your CI/CD pipeline. Your agent's mood tracks your deploy health.
# .github/workflows/deploy.yml
jobs:
deploy:
steps:
- uses: actions/checkout@v4
- run: npm install
- run: npm run deploy
- name: Signal deploy success
if: success()
run: npx agent-pet-state signal approval
env:
PET_STATE_FILE: ./state.json
- name: Signal deploy failure
if: failure()
run: npx agent-pet-state signal engagement-dead
env:
PET_STATE_FILE: ./state.jsonEvery green build boosts your agent's mood. Every red build dampens it. Your agent's personality reflects the health of your codebase.
The idea
Truth Terminal showed that AI agents with persistent internal state are more engaging than stateless ones. But nobody shipped a clean, reusable package for it.
This is that package. Four stats. Real-world signals. Mood-driven register shifts. Streaks and achievements for interactive play. Works with any agent framework — Claude Code, OpenAI, local LLMs, whatever.
Give your agent an inner life.
License
MIT
