Proven
Applications often need to resolve implicit context (like current project, user session, or workspace) from multiple potential sources with conflicting information. Without clear precedence rules, context resolution becomes unpredictable and error-prone. The Context Resolution Pattern addresses:
The Context Resolution Pattern resolves implicit context from multiple sources using clear precedence rules, ensuring predictable and consistent context determination across the application.
Core concept:
class ProjectContext:
"""Resolves project from various sources"""
def __init__(self, repository: ProjectRepository, llm: LLMClient):
self.repo = repository
self.llm = llm
self._session_memory: Dict[str, str] = {}
async def resolve_project(
self,
intent: Intent,
session_id: str,
confirmed: bool = False
) -> Tuple[Project, bool]:
"""
Resolution hierarchy:
1. Explicit project_id (always wins)
2. Session history (if confirmed)
3. LLM inference from message
4. Default project fallback
"""
# 1. Explicit always wins
if project_id := intent.context.get("project_id"):
project = await self.repo.get_by_id(project_id)
if not project:
raise ProjectNotFoundError(project_id)
return project, False
# 2. Session history
if session_id in self._session_memory and confirmed:
project = await self.repo.get_by_id(self._session_memory[session_id])
return project, False
# 3. Inference
inferred = await self._infer_from_message(intent)
if inferred:
self._session_memory[session_id] = inferred.id
needs_confirm = session_id in self._session_memory and \
self._session_memory[session_id] != inferred.id
return inferred, needs_confirm
# 4. Default fallback
default = await self.repo.get_default_project()
if default:
return default, True
raise NoProjectAvailableError("No project context available")
async def _infer_from_message(self, intent: Intent) -> Optional[Project]:
"""Use LLM to infer project from message content"""
projects = await self.repo.list_active_projects()
if not projects:
return None
project_context = "\n".join([f"- {p.name}: {p.description}" for p in projects])
prompt = f"""
Given this message: "{intent.message}"
And these available projects:
{project_context}
Which project is this message most likely referring to? Return just the project name or 'none'.
"""
response = await self.llm.complete(prompt)
for project in projects:
if project.name.lower() in response.lower():
return project
return None
class ContextResolver[T]:
"""Generic context resolution pattern"""
def __init__(self, sources: List[ContextSource[T]]):
self.sources = sorted(sources, key=lambda s: s.priority, reverse=True)
async def resolve(self, context_data: Dict[str, Any]) -> T:
"""Resolve context using source priority hierarchy"""
for source in self.sources:
try:
result = await source.resolve(context_data)
if result:
return result
except ContextResolutionError:
continue # Try next source
raise ContextNotResolvableError("No source could resolve context")
class ExplicitContextSource(ContextSource[Project]):
"""Highest priority - explicit specification"""
priority = 100
async def resolve(self, context_data: Dict[str, Any]) -> Optional[Project]:
project_id = context_data.get("project_id")
if project_id:
return await self.repository.get_by_id(project_id)
return None
class SessionContextSource(ContextSource[Project]):
"""Medium priority - session memory"""
priority = 50
async def resolve(self, context_data: Dict[str, Any]) -> Optional[Project]:
session_id = context_data.get("session_id")
if session_id and context_data.get("confirmed"):
return await self.get_session_project(session_id)
return None
Consolidated from:
pattern-catalog.md#11-context-resolution-pattern - Complete implementation with resolution hierarchy