Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,16 @@ The career agent is built around 7 traits, each with concrete implementation:

## Agent context layer

All agents in Tilto consume a shared `AgentContext` (`services/agent_context.py`) — a single entry point that bundles state, knowledge, tools, LLM clients and telemetry. This is the spine that prevents the "bazaar of disconnected agents" problem as the system grows.
All agents in Tilto consume a shared `AgentContext` (`services/agent_context.py`) — a single entry point that bundles **session state**, **knowledge base**, **tools**, **LLM clients**, **telemetry**, and a lazy bridge to the **long-term user context**. This is the spine that prevents the "bazaar of disconnected agents" problem as the system grows.

Two complementary layers:

| Layer | Lifetime | Purpose |
|---|---|---|
| **`AgentContext`** (per-job) | ~90s, one instance per agent run | Session state (location, conversation), knowledge base, tools, telemetry |
| **`UserContextService`** (long-term) | Persisted across sessions and agents | 360° view of a user: quizzes, analyses, orders, bookings, capsule listens, chat messages, consent history |

A future agent (support, follow-up, meta-analyser) reads `ctx.get_user_summary()` or `ctx.user_context_service.get_full_context()` and instantly knows *who this user is across their entire journey*. The `UserContextService` powers both the admin user-detail page and any agent that needs durable context.

```mermaid
flowchart LR
Expand Down Expand Up @@ -98,6 +107,7 @@ flowchart TD
User([User]) -->|voice + text| Perception[Perception<br/>chat coach + Whisper]
Perception --> Memory[(Short-term memory<br/>conversation, answers,<br/>audit trail)]
KB[(Knowledge base<br/>prompts, criteria,<br/>templates)] -.config.-> Writer
UCS[(UserContextService<br/>long-term:<br/>quizzes, analyses,<br/>orders, bookings…)] -.optional.-> Writer
Memory --> Writer

Writer[Writer<br/>Claude Sonnet + web_search]
Expand All @@ -121,7 +131,7 @@ flowchart TD
classDef store fill:#FBF1F6,stroke:#A11857,color:#1A1A2E
classDef tool fill:#fff7e6,stroke:#d4847a,color:#1A1A2E
class Writer,Critic llm
class Memory,KB,Publish,Draft store
class Memory,KB,UCS,Publish,Draft store
class WebSearch,Monitor tool
```

Expand All @@ -135,6 +145,8 @@ flowchart TD
| `_critic_evaluate(...)` | Orchestrates one validation cycle (build prompt → call critic → parse issues) |
| `_track_usage(...)` | Per-call telemetry: input/output tokens, web_search uses, USD cost |
| `get_usage_summary()` | Job-level total for monitoring and Slack alerts |
| `ctx.user_context_service` | Lazy access to long-term user context (history, orders, bookings) |
| `ctx.get_user_summary()` | Condensed snapshot of the user across all sessions |

### Telemetry & alerting

Expand Down Expand Up @@ -261,7 +273,8 @@ tilto/
│ ├── dashboard.py # User/admin dashboard
│ └── ...
├── services/
│ ├── agent_context.py # ★ AGENT CONTEXT (shared state, tools, telemetry)
│ ├── agent_context.py # ★ AGENT CONTEXT (per-job: state, tools, telemetry, LLM clients)
│ ├── user_context_service.py # ★ USER CONTEXT (long-term 360° view: history, orders, bookings)
│ ├── quiz_analysis_service.py # ★ CAREER AGENT (Writer ⇄ Critic loop on top of AgentContext)
│ ├── async_analysis_service.py # Job orchestration + monitoring/alerts
│ ├── conversation_eval_service.py # Coach IA (interview)
Expand Down
17 changes: 11 additions & 6 deletions cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,19 @@ steps:
'.'
]

# Step 0b: Cache longue durée sur les images GCS
# Step 0b: Cache longue durée sur les images GCS — skippé si _STORAGE_BUCKET est vide
- name: 'gcr.io/cloud-builders/gsutil'
entrypoint: 'bash'
args:
- '-m'
- 'setmeta'
- '-h'
- 'Cache-Control:public, max-age=31536000, immutable'
- 'gs://${_STORAGE_BUCKET}/production/**'
- '-c'
- |
if [ -z "${_STORAGE_BUCKET}" ]; then
echo "⏭️ _STORAGE_BUCKET non défini — skip cache headers GCS"
exit 0
fi
gsutil -m setmeta \
-h 'Cache-Control:public, max-age=31536000, immutable' \
"gs://${_STORAGE_BUCKET}/production/**"

# Step 1: Test de l'image
- name: 'gcr.io/$PROJECT_ID/quiz-app:$BUILD_ID'
Expand Down
5 changes: 5 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,11 @@ def __init__(self):
self.VALIDATOR_PROVIDER = config.get('VALIDATOR_PROVIDER', 'anthropic').lower()
self.OPENAI_VALIDATOR_MODEL = config.get('OPENAI_VALIDATOR_MODEL', 'gpt-4o-mini')

# Quiz chat immersif : feature flag lu depuis le JSON APP_CONFIG en prod
# (en dev/local, c'est lu via os.environ par BaseConfig)
quiz_chat_raw = config.get('QUIZ_CHAT_MODE', 'false')
self.QUIZ_CHAT_MODE = str(quiz_chat_raw).strip().lower() in ('true', '1', 'yes')

# Cloud Storage Buckets
self.STORAGE_BUCKET = config.get('STORAGE_BUCKET', self.STORAGE_BUCKET)
self.DATA_BUCKET = config.get('DATA_BUCKET', 'tilto-data')
Expand Down
Loading