Detailed walkthroughs of each action, showing realistic conversations between user and agent.
Scenario: You're new to Python's asyncio and want to actually understand it, not just get a summary.
You: @agentic-learning learn async/await in Python
Agent: Before I explain anything — what do you already know about async/await?
Even a rough intuition counts. What problem do you think it's solving?
You: I think it has to do with running things at the same time?
Agent: Good instinct — you're pointing at the right problem. Let me add precision.
async/await is about concurrency, not parallelism. The difference matters:
parallelism = two things happening at the exact same moment (two CPUs working).
concurrency = one thread switching between tasks while one is waiting (e.g. for
a network response), so nothing is wasted sitting idle.
Python's asyncio runs on a single thread. It can't do two things simultaneously,
but it can do other work while waiting for I/O.
Now — generation exercise. Complete this function:
async def fetch_user(user_id: int):
response = await _______________
return response.json()
What goes in the blank, and why does it need `await`?
Scenario: You've just finished writing a module and want to test your understanding before moving on.
You: @agentic-learning quiz
Agent: I'll quiz you on the current file. Answer each question before I show the next.
Question 1 of 4:
This function is called in three places in the codebase.
Without looking — what does `normalize_weights()` return?
You: A list of floats that sum to 1.0
Agent: Correct. It returns a list of floats normalized so they sum to 1.0.
The edge case worth noting: if the input list is all zeros, it raises
a ValueError rather than returning zeros.
Question 2 of 4:
What's the difference between `fit()` and `fit_transform()` in this class?
Scenario: You need to implement a debounce function in JavaScript and you want to work through it rather than just get the answer.
You: @agentic-learning struggle implement a debounce function in JavaScript
Agent: [Hint 1 — Conceptual direction]
Think about what "debounce" means in physical electronics: a button that
bounces several times when pressed but should only register once.
In code, what mechanism exists in JavaScript for "do this, but not yet"?
You: setTimeout?
Agent: Exactly. Now think about what needs to happen when the function is called
again before the delay has elapsed.
Give it a try — don't worry about getting it perfect.
You: function debounce(fn, delay) {
let timer;
return function() {
setTimeout(fn, delay);
}
}
Agent: You have the right structure and you found the right tool.
One thing is missing: you're creating a new timer every call, but you're
not cancelling the previous one.
[Hint 2 — Structural hint]
Each time the returned function is called, it should:
1. Cancel whatever timer is currently pending
2. Start a fresh timer
JavaScript has a built-in function for step 1. What is it?
You: clearTimeout?
Agent: Yes. Try combining clearTimeout and setTimeout now.
You: function debounce(fn, delay) {
let timer;
return function() {
clearTimeout(timer);
timer = setTimeout(fn, delay);
}
}
Agent: That's it. Clean and correct.
One thing to add: the returned function should forward its arguments to `fn`,
so the debounced function can be used in place of the original.
How would you pass `this` and arguments through?
(If you want to stop here and look it up: that's the right call.
The core logic is solid.)
Scenario: You've spent 2 hours building a data pipeline and want to close the session properly.
You: @agentic-learning reflect
Agent: Let's close this session with three questions. Take your time with each.
1. What did you learn today — what concepts or patterns clicked that didn't
before, or what did you understand more deeply?
You: I understood how generator functions work in Python. I kept using them
without really knowing why they were memory-efficient.
Also got clearer on when to use list comprehensions vs generators.
Agent: Good. That distinction (eager vs lazy evaluation) is foundational
and transfers to a lot of other contexts.
2. What was your goal when you started this session?
You: Build a pipeline that processes 10M rows without loading everything in memory.
Agent: 3. Given that goal — what do you still feel uncertain about?
What's the thing you'd want to understand better before calling this done?
You: I'm not sure how to handle backpressure if the consumer is slower than
the producer. I just ignored it for now.
Agent: ── Reflection summary ──────────────────────────────────────
What you covered: lazy evaluation via generators; list comprehension
vs generator expression trade-offs; memory-efficient pipeline design.
Gap identified: backpressure handling — what happens when the consumer
can't keep up with the producer.
Suggested next step:
@agentic-learning learn backpressure in Python async generators
Or search: "asyncio queue backpressure Python" — the asyncio.Queue class
is the standard tool here and will map directly onto what you built today.
Scenario: After a learning session, you want to make sure the concepts stick.
You: @agentic-learning space
Agent: Based on this session, here's what I'd suggest revisiting:
Writing to docs/revisit.md...
── Tomorrow ─────────────────────────────────────
• Generator lazy evaluation: you understood it today but it's new —
try explaining it out loud without looking at code.
── In 3 days ────────────────────────────────────
• List comprehension vs generator: you're clear on the basics,
reinforce the edge cases (large files, chained generators).
── In 1 week ────────────────────────────────────
• asyncio pipeline structure: solid foundation, good to revisit
once you've added the backpressure handling.
✓ Written to docs/revisit.md
Scenario: You want to build an auth system and need to think it through before writing any code.
You: @agentic-learning brainstorm auth system for a multi-tenant SaaS
Agent: Let me look at what you have in the codebase before we start...
[reads relevant files]
I see you're using FastAPI with a PostgreSQL database.
One question to start:
Is each tenant completely isolated (separate databases / schemas),
or do all tenants share tables with a tenant_id column?
You: Shared tables, tenant_id column.
Agent: Good — that shapes things significantly.
Next question: what's your threat model for tenant isolation?
Specifically: are you worried about accidental data leakage
(a bug exposes tenant A's data to tenant B), or active attacks
(a tenant trying to access another's data intentionally)?
You: Mainly accidental leakage. We trust our users.
Agent: That's the more common case and it simplifies things.
I see three reasonable approaches:
A — Row-level security in PostgreSQL (recommended)
Set a session variable per request; Postgres enforces the filter
automatically on every query. Hard to accidentally forget.
Trade-off: requires PostgreSQL-specific features, adds a small
per-query overhead.
B — Application-level tenant middleware
A FastAPI dependency injects tenant_id into every query.
Simple to understand; works with any DB.
Trade-off: one missed dependency = data leak. Relies on developer discipline.
C — ORM-level global filter (e.g. SQLAlchemy query filter)
Register a default filter on every model.
Trade-off: can be bypassed with raw queries; less visible than RLS.
My recommendation: A, with B as a belt-and-suspenders backup.
RLS gives you DB-level enforcement even if application code has a bug.
Does this match your constraints?
(After approval, agent writes docs/brainstorm/2026-03-02-auth-system.md)
Scenario: You're reviewing code you wrote a week ago and want to test if you still understand it.
You: @agentic-learning explain-first
Agent: Looking at the current file...
Before I say anything: walk me through what `build_feature_matrix()` does.
Explain it as if you're teaching someone who hasn't seen it.
Take your time.
You: It takes a list of user events, groups them by user_id, and for each user
builds a vector of features — like how many times they clicked, their last
active date, that kind of thing. Returns a numpy array.
Agent: Good — you have the right mental model.
Two things to add:
1. The groupby uses a defaultdict internally, which means missing users
get a zero vector rather than raising a KeyError. Worth knowing when
you debug downstream issues.
2. The "last active date" is stored as days-since-epoch (an integer),
not a datetime — which affects how you'd interpret the feature weights
in a model.
Both are easy to miss if you're just reading fast.
Scenario: You just decided to use Redis for session storage instead of the database and want to record it.
You: @agentic-learning either-or use Redis vs database for session storage
Agent: Let me capture this properly.
What's the context — what are you building and what triggered this decision?
You: Building the session layer for the auth system. We need to store JWT
refresh tokens so we can revoke them. Decided to use Redis instead of
a sessions table in Postgres.
Agent: Good. What were the real alternatives you considered?
(You mentioned Redis vs database — any others?)
You: Also considered stateless tokens with short expiry and no revocation.
Three options: Redis, Postgres table, or just accept no revocation.
Agent: What made you choose Redis?
You: Fast reads, built-in TTL, doesn't pollute the main DB schema.
The no-revocation option felt too risky for a SaaS product.
Agent: What do you expect to happen as a result of this choice?
You: We'll need to add Redis to infrastructure. Slightly more ops complexity.
But instant revocation on logout and easy token TTL management.
Agent: ✓ Appended to docs/decisions/2026-03-02-decisions.md
## [14:35] Session storage: Redis vs Postgres vs stateless
**Context:** Building the session layer for JWT refresh token revocation
in a multi-tenant SaaS auth system.
**Paths considered:**
- **A — Redis:** Fast reads, built-in TTL, doesn't pollute main DB schema.
- **B — Postgres sessions table:** No new infrastructure; slower reads; schema noise.
- **C — Stateless (no revocation):** Zero ops cost; tokens live until expiry.
**Chosen:** A — Redis
**Rationale:** Fast reads + native TTL + clean separation from main DB.
No-revocation felt too risky for a product with paying customers.
**Expected consequences:** Additional infrastructure dependency (Redis).
Ops complexity increases slightly. Gain: instant token revocation on logout.
**Outcome (to fill later):** _pending_
Scenario: You've just cloned an unfamiliar repo and want to understand what it is before touching anything.
You: @agentic-learning explain
Agent: Reading the project...
[scans README.md, SKILL.md, references/, EXAMPLES.md, install.sh]
── agentic-learning — Comprehension log ─────────────────────────
Generated: 2026-03-03 00:09
### What this project does
An agent skill that turns an AI coding assistant into a learning
partner. Instead of handing over answers, it guides users through
eight structured actions grounded in neuroscience (retrieval,
spacing, generation, reflection) and philosophy (Kierkegaard's
Either/Or). Installable in Windsurf, Cursor, Copilot, and any
AgentSkills-compatible agent.
### Architecture overview
Single SKILL.md file drives all behavior — the agent reads it as
instructions. Three reference files provide deeper context:
learning-science.md (the research), struggle-ladder.md (hint system),
either-or-format.md (decision journal format). No code to run — pure
markdown instructions for the agent.
### Entry points
- Install: `npx skills add FavioVazquez/agentic-learn`
- Use: `@agentic-learning <action>` in any compatible agent
- All 8 actions are defined in SKILL.md
### Key concepts to understand
1. The skill body is agent instructions, not user docs — write it
for the model to read and follow
2. `description` in frontmatter is the trigger — specificity matters
3. All output files go into the user's project (docs/), not the skill
4. The "productive struggle" principle governs all actions — the agent
must not short-circuit the user's cognitive effort
5. either-or and brainstorm produce persistent artifacts (markdown files)
### Non-obvious things
- The skill is installed as a symlink by `npx skills` — edits to the
source repo are reflected immediately without reinstalling
- `explain-first` and `explain` look similar but are opposite directions:
explain-first = user explains TO the agent; explain = agent explains
TO the user
- version is "1.1" in SKILL.md — bump this on any behavioral change
### Open questions
- No test suite exists yet for verifying agent compliance with the
skill's constraints (the "wait before answering" rule especially)
- CONTRIBUTING.md not yet written
### Suggested learning path
1. Read SKILL.md top to bottom — understand each action's constraints
2. Run through EXAMPLES.md — see what correct behavior looks like
3. Install and test each action once before contributing changes
4. Read references/ to understand the science behind the design choices
✓ Written to docs/project-knowledge.md
Is there a specific area you want to go deeper on, or something
that seems wrong in my reading?
Scenario: You've been working on the project for a while and run explain again — it appends rather than overwrites.
You: @agentic-learning explain references/
Agent: Reading the references/ directory specifically...
── agentic-learning — Comprehension log ─────────────────────────
Generated: 2026-03-10 14:22 (focused: references/)
### What this area does
Three supporting documents the agent reads during skill execution.
They are NOT user-facing docs — they are instructions and context
for the agent to draw on when running specific actions.
### Non-obvious things
- learning-science.md is cited in the SKILL.md body — if you update
the research section, the agent will use it automatically
- struggle-ladder.md defines 4 hint levels plus extended hints —
the "harder" mode collapses levels upward
- either-or-format.md contains 3 full worked examples, which is the
most valuable part for calibrating agent behavior
✓ Appended to docs/project-knowledge.md
Scenario: You've been learning Python generators, async/await, and decorators across separate sessions. Instead of going deep on one again, you want a session that mixes all three to force real discrimination.
You: @agentic-learning interleave
Agent: I can see you've been working across generators, async/await, and decorators
recently. I'll mix questions from all three — don't expect them to stay in
one topic.
Question 1 of 5:
What does this return, and why?
def gen():
yield 1
yield 2
yield 3
list(gen())
You: [1, 2, 3] — because list() exhausts the generator by calling next() repeatedly
until StopIteration.
Agent: Exactly right. The key detail you named — StopIteration — is what list()
is actually catching internally. That's a non-obvious thing most people miss.
Question 2 of 5:
Different topic. Complete this sentence:
"The difference between `async def` and a regular `def` is that async def
returns a ________, which only runs when ________."
You: Returns a coroutine, which only runs when awaited or passed to an event loop.
Agent: Correct on both. Worth adding: the coroutine object is created immediately
when you call the function — it just doesn't execute until driven.
Question 3 of 5:
Back to generators. What's the difference between these two:
# A
data = [x * 2 for x in range(1000000)]
# B
data = (x * 2 for x in range(1000000))
You: A builds the whole list in memory immediately. B is a generator expression —
it produces values lazily, one at a time, so memory usage stays flat.
Agent: Right. The shape is identical, the brackets are the only difference —
and the memory behaviour is completely different. That's worth remembering
as a gotcha in code review.
Question 4 of 5:
New topic. What does a decorator actually do at the Python level?
Explain it mechanically, not conceptually.
You: It wraps a function — takes the original function as input, returns a new
function that usually calls the original inside it. The @ syntax is just
shorthand for: my_func = decorator(my_func)
Agent: That's the cleanest possible explanation. The desugaring (@syntax =
reassignment) is exactly what people miss when they first see decorators.
Question 5 of 5 — mixing two topics:
Could you write a decorator that measures how long a coroutine takes to run?
You don't need to write it perfectly — just sketch the structure.
You: import time, functools, asyncio
def timer(func):
@functools.wraps(func)
async def wrapper(*args, **kwargs):
start = time.time()
result = await func(*args, **kwargs)
print(f"Took {time.time() - start:.2f}s")
return result
return wrapper
Agent: That's correct and complete. Two things worth noting:
1. The wrapper must be `async def` because it awaits the original function
2. functools.wraps preserves the original function's metadata — easy to forget
── Session summary ──────────────────────────────────────────
Solid across the board. Strongest: generators (mechanics and memory model)
and the decorator desugaring.
Worth revisiting: the event loop / coroutine lifecycle — you got the surface
right but the "driven by the event loop" part was thin.
Suggested follow-up:
@agentic-learning struggle write an async event loop from scratch (simplified)
Scenario: You're trying to learn Kubernetes and everything feels connected to everything else — you don't know where to start.
You: @agentic-learning cognitive-load Kubernetes
Agent: Before I break it down — what specifically feels overwhelming?
Is it:
A — Too many new terms (pod, node, cluster, deployment, service...)
B — Too many steps to get something running
C — The pieces don't connect — you can read the docs but can't
build a mental model of how it all fits
You: Honestly C mostly. I've read the docs but I can't picture how a request
actually gets from the internet to my container.
Agent: That's the right question to start with — request flow is the spine
everything else hangs on.
Here's the dependency map — what needs to exist before each thing works:
Internet → LoadBalancer Service
→ Ingress Controller (optional but common)
→ ClusterIP Service
→ Pod (your container)
→ Node (the machine the pod runs on)
→ Cluster (the set of nodes)
The key insight: a Pod is the smallest unit, but you almost never
talk to it directly. Services are stable addresses that route to Pods,
because Pods are ephemeral — they die and get replaced.
Here's a 5-step learning plan, each piece small enough to hold in
working memory on its own:
Step 1: Pod — what it is and how to run one manually
Why it matters: everything else is built on top of this
Step 2: Service (ClusterIP) — how to give a Pod a stable address
Why it matters: Pods die; Services don't
Step 3: Deployment — how Kubernetes manages Pod lifecycle for you
Why it matters: you never create Pods directly in production
Step 4: Ingress — how external HTTP traffic gets routed in
Why it matters: this is what connects your app to the internet
Step 5: Namespace — how to isolate workloads in one cluster
Why it matters: required for any multi-team setup
Does this order make sense, or is there something you think
belongs earlier?
You: This is really helpful. Can we start with Step 1?
Agent: @agentic-learning learn Kubernetes Pods — starting now.
Before I explain anything: what do you think a Pod is?
Even a rough guess counts.
These actions work well together. A few typical session patterns:
Onboarding a new repo:
# Understand what you're working with before touching anything
@agentic-learning explain
# Design the first change before coding it
@agentic-learning brainstorm caching strategy for the API
# Record the key architectural decision
@agentic-learning either-or use Redis cache vs in-memory LRU
# Work through the hardest part with productive struggle
@agentic-learning struggle implement LRU cache in Python without a library
# Test your understanding of what you built
@agentic-learning quiz
# Close the session properly
@agentic-learning reflect
@agentic-learning space
Deep review session (reinforcing past learning):
# Mix topics from past sessions — harder but stickier than going deep on one
@agentic-learning interleave
# Close with spacing reminders so today's review is reinforced over time
@agentic-learning space
Tackling something overwhelming:
# Break it into working-memory-sized pieces first
@agentic-learning cognitive-load distributed tracing in microservices
# Then learn the first piece properly
@agentic-learning learn Step 1 concept from the plan
# Struggle through the implementation
@agentic-learning struggle implement the first piece
# Reflect on what you understood vs. what you just followed
@agentic-learning reflect