rnr1721/depthnet
DepthNet is a Laravel package for building and querying hierarchical, depth-aware data structures. It simplifies parent-child relationships, nested categories, and multi-level networks with Eloquent-friendly APIs for managing trees.
This package turns a Laravel app into a persistent agent runtime: presets (named agents with prompts and capabilities), plugins that extend what an agent can do (Handoff, Wake, Mode), and per-preset capabilities (vision, embedding, and now STT/TTS). The admin UI is the control plane; almost everything a developer configures day-to-day lives there rather than in code.
Minimal path to a working agent:
php artisan schedule:work locally, cron in prod). This is not optional once you use Wake — nothing fires without the tick.+10m wake to see the full sleep-and-return cycle.Where to look first, in order of payoff: Presets (the unit of configuration), Capabilities (provider wiring), Wakes (scheduling surface, including user-designed wakes), then the plugin registry. If you're integrating voice, jump straight to Admin → Capabilities and read the STT/TTS provider entries before touching the UI — the browser/local split determines most of your architecture.
The best first use case is not voice. It's a single preset with Wake plus Mode switching: it exercises the scheduler, the prompt substrate, and the agent's self-inspection surface ([[wake_schedule]]) all at once, and it fails loudly and visibly if your tick or queue is misconfigured — which is exactly what you want on day one.
Wake scheduling. Treat wakes as the temporal counterpart to handoffs: a way for one turn to leave work for a later turn without holding a worker open. In practice:
+2h) for retry/backoff and short follow-ups inside a workflow.2026-07-12 14:00) for one-shot reminders tied to real-world events.14:30) and every 6h for heartbeat-style agents — this is the replacement for the perpetually-spinning loop pattern, and it's strictly cheaper.0 9 * * MON).p850, +20p) only on presets that already operate in subjective time units; mixing pulse and wall-clock semantics in one preset is a debugging trap.The idiomatic workflow is memo → wake → goal: a memo handles the next cycle, a wake handles "come back to this at a chosen moment," and a goal provides the long-term direction the wake serves. If you find yourself writing a loop that polls, replace it with a wake.
User-designed wakes. When product wants a scheduled agent behavior but doesn't want to grant the agent the Wake plugin, create the wake in Admin → Wakes. It's dispatched identically but tagged (user) so the agent can distinguish operator intent from its own scheduling. This is the right tool for compliance-driven or irreversible actions: the agent can see the schedule but not author it.
Voice as two independent capabilities. STT and TTS are configured separately per preset, and the combinations are meaningfully different:
The bundled voice-service container (faster-whisper + Piper) is a sane default for a long-memory agent where "what the agent hears and says stays on the host" is a product requirement, not a preference. Five languages ship; transcription runs roughly 2× realtime on a mid-range CPU, which is fine for async voice notes and marginal for live conversation — pair local STT with browser STT if you need low-latency dialogue.
Mode self-authorship. Mode now has two independently switchable layers: prompt switching (multiple named variants, agent picks based on its read of the situation) and prompt self-editing (targeted find/replace, or full rewrite behind an off-by-default flag). Enable switching first and let it stabilize before enabling editing. When you do enable editing:
Composition tips. Handoff (spatial) and Wake (temporal) compose cleanly: a wake fires, the agent decides it can't finish, and hands off to a human or another preset — the handoff is the exit, the wake was the entry. Attach voice only to presets that need it; capability resolution is per-preset, so an unused TTS provider costs you nothing at runtime but does cost you a container if you run the bundled service.
At-least-once delivery is the contract. Recurring wakes recompute after successful dispatch, so a crashed worker re-fires rather than dropping the wake. That's the correct tradeoff for reliability, but it means your wake handlers must be idempotent. If a wake triggers an outbound message, a charge, or a state transition, key it on the wake ID and check before acting. Do not assume exactly-once.
Nothing fires without the scheduler. The single most common "wakes are broken" report is a missing schedule:work in dev or a broken cron entry in prod. Wake is dispatched by an external tick, not by the agent loop — verify the tick independently before debugging anything else.
Timezone semantics differ per grammar. Relative and interval wakes are timezone-agnostic; absolute and daily wakes are not. Pin the timezone explicitly in config and be aware that "daily at 14:30" means different things to a scheduler running in UTC and an admin UI rendering in local time. Cron expressions inherit the scheduler's timezone unless overridden.
Pulse scheduling is opt-in and preset-specific. p850 only means something to a preset operating in subjective pulse units. Passing pulse strings to a wall-clock preset will either error or silently misbehave — validate the grammar against the preset's mode rather than accepting whatever the agent emits.
The agent can see its own calendar. [[wake_schedule]] is injected as a live view of upcoming wakes, which is what makes the feature usable ("a clock on the wall") but also means scheduled instructions are visible context. Don't store secrets in wake payloads. Conversely, if you want the agent to not know about something, a user-designed wake still appears — the (user) marker tells it the wake is yours, not that it's invisible.
User-designed wakes are the escape hatch for irreversible actions. If you're tempted to give a preset the Wake plugin just so it can schedule a nightly report, consider an admin-created wake instead. It keeps the plugin surface small and makes the schedule auditable by humans.
Voice provider mismatches are silent-ish. Browser STT depends on the Web Speech API and won't behave uniformly across browsers; local STT is what buys you Firefox support. Browser TTS quality varies wildly by OS and voice pack, so test on the machines your users actually have rather than your dev laptop. For any non-browser channel, assume browser providers are unavailable and route to the OpenAI-compatible family.
The bundled voice-service is a real container with real resource needs. faster-whisper + Piper on a mid-range CPU is roughly 2× realtime for transcription — fine for queued voice notes, not fine for concurrent live sessions. Budget CPU, not just memory, and put it behind a queue for anything user-triggered.
Full rewrite is a safeguard for a reason. It's off by default because it's the highest-blast-radius edit path: one bad rewrite can discard a carefully calibrated prompt, and the version history is your only recovery. Before enabling it, confirm revert works end-to-end in staging — including the admin-UI human-edit path, which is versioned separately in the timeline but shares the same revert mechanism.
Drift is a review process, not a feature flag. Versioning, diff, and revert are conditions of allowing self-editing, not conveniences. Put a recurring human review on the calendar (a wake is a fine place to schedule the reminder, fittingly) and diff distant versions, not the most recent pair. Without required annotations, the history degrades quickly into a list of unexplained snapshots.
Extension points. New providers plug in at the capability layer (STT/TTS/vision/embedding), so adding a cloud vendor is a config + adapter job rather than a core change. New agent behaviors belong in plugins; resist putting scheduling logic in application code, since anything outside the wake/queue boundary bypasses the at-least-once guarantees and the [[wake_schedule]] visibility the agent relies on to reason about its own future.
How can I help you explore Laravel packages today?