One thing I’ve been thinking about more while building AdamI is how often autonomy gets described as the ability to keep acting.

The agent receives a goal.

It makes a plan.

It uses tools.

It keeps going until the task is done.

That sounds reasonable.

But the more I work on persistent behavior, the more incomplete that picture feels.

Sometimes the correct next action is not another action.

Sometimes the system should wait.

AdamI task states showing waiting, scheduled, paused and completed tasks, illustrating that waiting can be an intentional part of autonomous behavior.
Conceptual view of task states. Waiting, scheduled, paused, and completed are shown as distinct behaviors. This is a design illustration, not a claim that AdamI currently has a mature temporal decision system.

Acting is easy to imagine

Most agent demos are built around visible activity.

The model is thinking.

A tool is being called.

A browser is moving.

Code is being written.

Tasks are being completed.

That makes autonomy look like forward motion.

And for short tasks, that’s often enough.

But long-running systems live in a different environment.

Things are not always ready.

An API may be unavailable.

A permission may not have been granted yet.

A file may be locked.

A human may need to approve something.

A dependency may not exist yet.

A task may only make sense after some external condition changes.

If the system’s only mode is:

What can I do next?

then it can easily start doing the wrong thing simply because it feels pressure to keep moving.


“Do nothing” can be a valid decision

This sounds trivial, but I don’t think it is.

A system that can act but cannot intentionally refrain from acting is missing something important.

Imagine an agent sees that a dependency is unavailable.

It could:

  • retry immediately
  • try a workaround
  • change the task
  • ask for help
  • wait

Those are all technically possible.

But they are not equally good.

Sometimes retrying immediately just wastes tokens and API calls.

Sometimes a workaround creates more state that has to be cleaned up later.

Sometimes asking the user every thirty seconds is worse than waiting ten minutes.

Sometimes the best decision really is:

Nothing should happen yet.

That feels like part of autonomy too.


Waiting is not the same as stopping

This is where the problem gets more interesting.

If a system waits, it still has to remain a system.

It needs to know:

  • what it is waiting for
  • why it is waiting
  • when it started waiting
  • what condition would wake it up
  • whether the condition has changed
  • what to do when it resumes

Otherwise “waiting” is just another word for forgetting.

A task that pauses for two hours should not wake up as a completely new task.

The system needs to preserve enough state to continue from the right place.

That makes waiting a persistence problem.


A task needs more states than running and finished

Earlier versions of how I thought about tasks were too simple.

Something was basically:

  • pending
  • running
  • done
  • failed

But real long-running work has more texture than that.

A task may be:

  • waiting for an external event
  • waiting for permission
  • blocked by another task
  • paused deliberately
  • scheduled for later
  • retrying after a delay
  • cancelled
  • timed out
  • waiting for human input

Those states matter because they change what the system should do next.

A task waiting for permission should not behave like a failed task.

A task waiting until tomorrow should not behave like a task that crashed.

A task paused by the user should not automatically restart because the agent sees an unfinished goal.

The difference is not just metadata.

It affects behavior.


Retry is one of the easiest places to get this wrong

Retries are a good example.

The naive behavior is:

It failed. Try again.

Then:

It failed again. Try again.

That can look persistent.

But it’s not very intelligent persistence.

If the failure condition has not changed, repeating the same action may just burn compute.

A better system needs some sense of:

  • retry limits
  • backoff
  • whether the failure is transient
  • whether the environment changed
  • whether another strategy is justified
  • whether the task should be escalated

This is where time starts becoming part of reasoning.

Not only:

What should I do?

but:

When should I try again?

That is a different question.


Time becomes part of state

A chatbot mostly lives in conversational time.

The user says something.

The model responds.

A persistent system has to deal with actual time.

Ten seconds can matter.

So can ten minutes.

So can tomorrow.

If a task says:

Check again after 30 minutes.

the system has to preserve that instruction outside the current reasoning episode.

If a process is waiting until a deadline, the deadline needs to survive a restart.

If another task changes the condition earlier than expected, the waiting task may need to wake up immediately.

This starts to look less like prompt engineering and more like runtime behavior.

Which is exactly the kind of thing I keep running into with AdamI.


Background activity is not the same as constant activity

I’ve been interested in background processes for a while because they seem important for persistence.

But I’m realizing that “background activity” is probably the wrong mental image if it implies the system should always be busy.

A good background system may spend most of its time doing very little.

It may be:

  • watching
  • sleeping
  • waiting
  • checking a condition occasionally
  • waking up only when something changes

That is still active system behavior.

It just doesn’t look dramatic.

In fact, this may be more useful than having an agent constantly generate new actions.


Waiting also creates a control problem

There is another side to this.

If an agent can schedule itself to act later, who controls that future action?

Suppose the system decides:

Retry this tomorrow.

By tomorrow:

  • the user’s intent may have changed
  • the permission may have expired
  • the tool may no longer be available
  • the task may have been cancelled
  • the environment may be different

So a future action should not inherit authority automatically just because it was previously planned.

The system needs to re-check reality.

And probably re-check permission too.

That connects directly to something I’ve been thinking about in Guardian:

Authority should be evaluated at execution time, not assumed from an old plan.

A plan can persist.

Permission may not.


Resume should begin with verification

This also connects to the state-first workflow I’ve been using with multiple coding agents.

When a task resumes, I don’t want the system to blindly continue from an old internal assumption.

It should first inspect what changed.

For example:

A task pauses because an external service is unavailable.

Two hours later, it wakes up.

Before continuing, it should check:

  • Is the service actually available now?
  • Is the task still relevant?
  • Has someone else already completed it?
  • Has the state changed?
  • Does the permission still exist?

So the flow becomes something like:

Wait
→ Wake
→ Inspect
→ Verify
→ Continue

Not:

Wait
→ Continue blindly

That small difference seems important.


A persistent system needs to know why it is waiting

This is another thing I think needs to be explicit.

“Waiting” without a reason is not very useful.

A task should probably be able to say something like:

Waiting for API availability.

or:

Waiting for human approval.

or:

Waiting until 09:00.

or:

Waiting because retry backoff has not expired.

That reason becomes part of state.

It helps the system know what kind of event should wake the task.

It also helps with observability.

If I look at AdamI and something is not happening, I want to know whether it is:

  • broken
  • idle
  • blocked
  • paused
  • waiting intentionally

Those are very different situations.


Observability matters when nothing happens

This is easy to overlook.

When an agent is actively using tools, there is usually something to inspect.

Logs.

Calls.

Outputs.

Changes.

Waiting is quieter.

But if the system is supposed to run for long periods, I still need to understand its inactive states.

I want to be able to ask:

Why is this task not running?

And get an answer better than:

Nothing happened.

A useful answer might be:

Waiting until 14:30 because the previous request hit a rate limit. Retry 2 of 4.

That kind of state makes the system much easier to trust.

Silence becomes explainable.


Not acting can be safer than acting

There is also a direct connection to control.

A highly capable system can usually find some action.

That does not mean it should.

If information is incomplete, permission is unclear, or the environment looks wrong, the safest valid action may be to defer.

This is one reason I increasingly dislike definitions of autonomy that focus only on initiative.

Initiative matters.

But so does restraint.

An agent that always finds a way forward may be impressive in a benchmark.

In a real system, it may also be dangerous.

Sometimes a good autonomous decision is:

I have enough capability to act, but not enough justification.

So I’ll wait.


The system needs a concept of “not yet”

I think this is the simplest way I can describe the problem.

A persistent agent needs more than:

  • yes
  • no

It needs:

not yet

Not yet because the condition is wrong.

Not yet because permission is missing.

Not yet because the cost is too high.

Not yet because another task has priority.

Not yet because the system is uncertain.

Not yet because time itself is part of the task.

That seems like a small addition.

But architecturally, it changes a lot.


AdamI is not there yet

I want to be clear about the current state.

AdamI has pieces related to task state, queues, lifecycle, background processing, persistence, and control.

But I do not think it currently has a mature temporal decision system.

It does not yet have a complete model for:

  • waiting conditions
  • scheduling
  • backoff
  • wake-up triggers
  • dynamic priority
  • time-aware authority
  • long-horizon pause/resume semantics

Those are still open design problems.

What I have now is enough to make the problem visible.

Not enough to say it is solved.


This may matter more as agents run longer

Short agent tasks can get away with simple behavior.

If the whole job lasts thirty seconds, “keep going until done” is often fine.

But as agents start operating for hours, days, or longer, waiting becomes unavoidable.

The environment changes.

Permissions change.

Humans intervene.

Dependencies fail.

Costs accumulate.

New information arrives.

A persistent agent has to live through all of that without turning every pause into a reset.

That makes waiting part of continuity.

And continuity is becoming one of the main things I care about in AdamI.


Knowing when not to act

I used to think autonomy was mostly about removing the need for constant human prompting.

Now I think that definition is too narrow.

A useful autonomous system should know:

  • when to act
  • when to continue
  • when to retry
  • when to ask
  • when to stop
  • when to wait

The last one may be more important than it sounds.

Because a system that can only move forward is not really choosing.

It is just executing.

The principle I’m keeping from this is:

Autonomy isn’t just knowing what to do next.
It’s knowing when not to do anything.

For a persistent system, waiting is not absence of behavior.

Sometimes, it is the behavior.


Digital Life Log #007

Building AdamI — a Digital Life in public.