ff-taskforce 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. ff_taskforce-0.1.0/.env.example +4 -0
  2. ff_taskforce-0.1.0/.gitignore +8 -0
  3. ff_taskforce-0.1.0/Architecture.md +285 -0
  4. ff_taskforce-0.1.0/CLAUDE.md +15 -0
  5. ff_taskforce-0.1.0/LICENSE +21 -0
  6. ff_taskforce-0.1.0/PKG-INFO +136 -0
  7. ff_taskforce-0.1.0/README.md +111 -0
  8. ff_taskforce-0.1.0/pyproject.toml +37 -0
  9. ff_taskforce-0.1.0/src/taskforce/__init__.py +3 -0
  10. ff_taskforce-0.1.0/src/taskforce/for-agent-layerinfo.md +16 -0
  11. ff_taskforce-0.1.0/src/taskforce/l1/__init__.py +3 -0
  12. ff_taskforce-0.1.0/src/taskforce/l1/for-agent-layerinfo-l1.md +8 -0
  13. ff_taskforce-0.1.0/src/taskforce/l1/schema/__init__.py +3 -0
  14. ff_taskforce-0.1.0/src/taskforce/l1/schema/for-agent-moduleinfo.md +47 -0
  15. ff_taskforce-0.1.0/src/taskforce/l1/schema/schema.py +35 -0
  16. ff_taskforce-0.1.0/src/taskforce/l2/__init__.py +6 -0
  17. ff_taskforce-0.1.0/src/taskforce/l2/config/__init__.py +3 -0
  18. ff_taskforce-0.1.0/src/taskforce/l2/config/config.py +65 -0
  19. ff_taskforce-0.1.0/src/taskforce/l2/config/for-agent-moduleinfo.md +24 -0
  20. ff_taskforce-0.1.0/src/taskforce/l2/cost_logger/__init__.py +3 -0
  21. ff_taskforce-0.1.0/src/taskforce/l2/cost_logger/cost_logger.py +48 -0
  22. ff_taskforce-0.1.0/src/taskforce/l2/cost_logger/for-agent-moduleinfo.md +21 -0
  23. ff_taskforce-0.1.0/src/taskforce/l2/for-agent-layerinfo-l2.md +17 -0
  24. ff_taskforce-0.1.0/src/taskforce/l2/panelist/__init__.py +3 -0
  25. ff_taskforce-0.1.0/src/taskforce/l2/panelist/for-agent-moduleinfo.md +23 -0
  26. ff_taskforce-0.1.0/src/taskforce/l2/panelist/panelist.py +52 -0
  27. ff_taskforce-0.1.0/src/taskforce/l2/session_logger/__init__.py +3 -0
  28. ff_taskforce-0.1.0/src/taskforce/l2/session_logger/for-agent-moduleinfo.md +22 -0
  29. ff_taskforce-0.1.0/src/taskforce/l2/session_logger/session_logger.py +48 -0
  30. ff_taskforce-0.1.0/src/taskforce/l3/__init__.py +3 -0
  31. ff_taskforce-0.1.0/src/taskforce/l3/for-agent-layerinfo-l3.md +7 -0
  32. ff_taskforce-0.1.0/src/taskforce/l3/roundtable/__init__.py +3 -0
  33. ff_taskforce-0.1.0/src/taskforce/l3/roundtable/for-agent-moduleinfo.md +30 -0
  34. ff_taskforce-0.1.0/src/taskforce/l3/roundtable/roundtable.py +102 -0
  35. ff_taskforce-0.1.0/src/taskforce/l4/__init__.py +3 -0
  36. ff_taskforce-0.1.0/src/taskforce/l4/for-agent-layerinfo-l4.md +6 -0
  37. ff_taskforce-0.1.0/src/taskforce/l4/taskforce_facade/__init__.py +3 -0
  38. ff_taskforce-0.1.0/src/taskforce/l4/taskforce_facade/for-agent-moduleinfo.md +25 -0
  39. ff_taskforce-0.1.0/src/taskforce/l4/taskforce_facade/taskforce_facade.py +40 -0
  40. ff_taskforce-0.1.0/src/taskforce/mcp_wrapper/__init__.py +3 -0
  41. ff_taskforce-0.1.0/src/taskforce/mcp_wrapper/__main__.py +3 -0
  42. ff_taskforce-0.1.0/src/taskforce/mcp_wrapper/mcp_wrapper.py +48 -0
  43. ff_taskforce-0.1.0/start-claude.bat +13 -0
  44. ff_taskforce-0.1.0/start-claude.ps1 +117 -0
  45. ff_taskforce-0.1.0/tests/__init__.py +0 -0
  46. ff_taskforce-0.1.0/tests/l1/__init__.py +0 -0
  47. ff_taskforce-0.1.0/tests/l1/schema/__init__.py +0 -0
  48. ff_taskforce-0.1.0/tests/l1/schema/test_schema.py +43 -0
  49. ff_taskforce-0.1.0/tests/l2/__init__.py +0 -0
  50. ff_taskforce-0.1.0/tests/l2/config/__init__.py +0 -0
  51. ff_taskforce-0.1.0/tests/l2/config/test_config.py +47 -0
  52. ff_taskforce-0.1.0/tests/l2/cost_logger/__init__.py +0 -0
  53. ff_taskforce-0.1.0/tests/l2/cost_logger/test_cost_logger.py +32 -0
  54. ff_taskforce-0.1.0/tests/l2/panelist/__init__.py +0 -0
  55. ff_taskforce-0.1.0/tests/l2/panelist/test_panelist.py +59 -0
  56. ff_taskforce-0.1.0/tests/l2/session_logger/__init__.py +0 -0
  57. ff_taskforce-0.1.0/tests/l2/session_logger/test_session_logger.py +36 -0
  58. ff_taskforce-0.1.0/tests/l3/__init__.py +0 -0
  59. ff_taskforce-0.1.0/tests/l3/roundtable/__init__.py +0 -0
  60. ff_taskforce-0.1.0/tests/l3/roundtable/test_roundtable.py +111 -0
  61. ff_taskforce-0.1.0/tests/l4/__init__.py +0 -0
  62. ff_taskforce-0.1.0/tests/l4/taskforce_facade/__init__.py +0 -0
  63. ff_taskforce-0.1.0/tests/l4/taskforce_facade/test_taskforce_facade.py +54 -0
@@ -0,0 +1,4 @@
1
+ OPENAI_API_KEY=
2
+ XAI_API_KEY=
3
+ ANTHROPIC_API_KEY=
4
+ GEMINI_API_KEY=
@@ -0,0 +1,8 @@
1
+ .env
2
+ __pycache__/
3
+ *.pyc
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .pytest_cache/
8
+ .claude/
@@ -0,0 +1,285 @@
1
+ # Taskforce - Architecture
2
+
3
+ 다수의 LLM 패널에 의제를 질의하고 구조화된 아이디어 풀을
4
+ 반환하는 Python 패키지.
5
+
6
+ 서로 다른 방식으로 발달한 모델들의 관점 다양성을 활용하여
7
+ robust한 아이디어 풀을 구축하는 것이 목적.
8
+ 프로그래머틱하게 import하여 작업흐름에 통합하는 용도.
9
+
10
+ ## 시스템 개요
11
+
12
+ ```mermaid
13
+ graph LR
14
+ CALLER[호출자]
15
+ RT[Roundtable]
16
+ PANEL[Panelist Pool]
17
+ SUM[Summarizer]
18
+
19
+ GPT[GPT 5.4]
20
+ GROK[Grok 4-1]
21
+ CLAUDE[Claude opus-4]
22
+ GEMINI[Gemini 2.5 Pro]
23
+
24
+ CALLER -->|roundtable.discuss(agenda)| RT
25
+ RT -->|병렬 질의| PANEL
26
+ PANEL --> GPT
27
+ PANEL --> GROK
28
+ PANEL --> CLAUDE
29
+ PANEL --> GEMINI
30
+ PANEL -->|raw opinions| RT
31
+ RT -->|분류 취합 요청| SUM
32
+ SUM -->|IdeaPool| RT
33
+ RT -->|IdeaPool| CALLER
34
+ ```
35
+
36
+ ## Ln 구조
37
+
38
+ ```
39
+ src/taskforce/
40
+ for-agent-layerinfo.md
41
+ __init__.py # Taskforce 노출
42
+
43
+ l1/
44
+ for-agent-layerinfo-l1.md
45
+ schema/
46
+ schema.py # ModelEntry, Opinion, IdeaPool (pydantic)
47
+ for-agent-moduleinfo.md
48
+ __init__.py
49
+
50
+ l2/
51
+ for-agent-layerinfo-l2.md
52
+ config/
53
+ config.py # EnvConfig: .env 로드, 모델 레지스트리
54
+ for-agent-moduleinfo.md
55
+ __init__.py
56
+ panelist/
57
+ panelist.py # LiteLLM 래퍼, 개별 모델 호출
58
+ for-agent-moduleinfo.md
59
+ __init__.py
60
+ session_logger/
61
+ session_logger.py # 세션 전문 로그 (~/.taskforce/logs/)
62
+ for-agent-moduleinfo.md
63
+ __init__.py
64
+ cost_logger/
65
+ cost_logger.py # 비용 요약 로그 (~/.taskforce/cost_logs/)
66
+ for-agent-moduleinfo.md
67
+ __init__.py
68
+
69
+ l3/
70
+ for-agent-layerinfo-l3.md
71
+ roundtable/
72
+ roundtable.py # 병렬 질의 + summarizer 분류 취합
73
+ for-agent-moduleinfo.md
74
+ __init__.py
75
+
76
+ l4/
77
+ for-agent-layerinfo-l4.md
78
+ taskforce_facade/
79
+ taskforce_facade.py # 최상위 퍼사드
80
+ for-agent-moduleinfo.md
81
+ __init__.py
82
+
83
+ mcp_wrapper/
84
+ mcp_wrapper.py # optional MCP 서버 래퍼
85
+ __init__.py
86
+ __main__.py
87
+
88
+ tests/
89
+ l1/schema/test_schema.py
90
+ l2/config/test_config.py
91
+ l2/panelist/test_panelist.py
92
+ l2/session_logger/test_session_logger.py
93
+ l2/cost_logger/test_cost_logger.py
94
+ l3/roundtable/test_roundtable.py
95
+ l4/taskforce_facade/test_taskforce_facade.py
96
+ ```
97
+
98
+ ### 의존성 흐름
99
+
100
+ ```
101
+ l1 (schema) -- pydantic (외부)
102
+ l2 (config) -- dotenv (외부) + l1
103
+ l2 (panelist) -- litellm (외부) + l1
104
+ l2 (session_logger) -- l1
105
+ l2 (cost_logger) -- l1
106
+ l3 (roundtable) -- l2 (panelist) + l1
107
+ l4 (taskforce) -- l2 (config, session_logger, cost_logger) + l3 (roundtable)
108
+ ```
109
+
110
+ ## 클래스 다이어그램
111
+
112
+ ```mermaid
113
+ classDiagram
114
+ direction TB
115
+
116
+ class EnvConfig {
117
+ +panel_models: list~ModelEntry~
118
+ +summarizer_model: ModelEntry
119
+ +caller_provider: str
120
+ +load_from_env(dotenv_path, caller_provider) EnvConfig
121
+ +get_active_panels() list~ModelEntry~
122
+ }
123
+
124
+ class ModelEntry {
125
+ +provider: str
126
+ +model_id: str
127
+ +api_key: str
128
+ +display_name: str
129
+ }
130
+
131
+ class Opinion {
132
+ +model_name: str
133
+ +content: str
134
+ }
135
+
136
+ class DivergentPoint {
137
+ +topic: str
138
+ +positions: dict~str, str~
139
+ }
140
+
141
+ class UniquePoint {
142
+ +point: str
143
+ +source_model: str
144
+ }
145
+
146
+ class IdeaPool {
147
+ +agenda: str
148
+ +common: list~str~
149
+ +divergent: list~DivergentPoint~
150
+ +unique: list~UniquePoint~
151
+ }
152
+
153
+ class Panelist {
154
+ +model_entry: ModelEntry
155
+ +ask_async(prompt, system_msg) Opinion
156
+ }
157
+
158
+ class Roundtable {
159
+ +panelists: list~Panelist~
160
+ +summarizer: Panelist
161
+ +gather(agenda, context) list~Opinion~
162
+ +summarize(agenda, opinions) IdeaPool
163
+ +discuss(agenda, context) IdeaPool
164
+ }
165
+
166
+ class Taskforce {
167
+ +config: EnvConfig
168
+ +roundtable: Roundtable
169
+ +init(caller_provider, dotenv_path) void
170
+ +discuss(agenda, context) IdeaPool
171
+ }
172
+
173
+ EnvConfig "1" --> "*" ModelEntry
174
+ IdeaPool "1" --> "*" DivergentPoint
175
+ IdeaPool "1" --> "*" UniquePoint
176
+ Panelist "1" --> "1" ModelEntry
177
+ Roundtable "1" --> "*" Panelist : panel
178
+ Roundtable "1" --> "1" Panelist : summarizer
179
+ Roundtable ..> IdeaPool : produces
180
+ Taskforce "1" --> "1" EnvConfig
181
+ Taskforce "1" --> "1" Roundtable
182
+ ```
183
+
184
+ ## 프로세스 시퀀스
185
+
186
+ ```mermaid
187
+ sequenceDiagram
188
+ participant C as 호출자
189
+ participant TF as Taskforce
190
+ participant RT as Roundtable
191
+ participant P1 as GPT 5.4
192
+ participant P2 as Grok 4-1
193
+ participant P3 as Claude opus-4
194
+ participant P4 as Gemini 2.5 Pro
195
+ participant SM as Summarizer
196
+
197
+ C->>TF: discuss(agenda, context)
198
+ TF->>RT: gather + summarize
199
+
200
+ Note over RT: 1단계: 패널 질의
201
+ par 병렬 호출
202
+ RT->>P1: 의제 + 컨텍스트
203
+ RT->>P2: 의제 + 컨텍스트
204
+ RT->>P3: 의제 + 컨텍스트
205
+ RT->>P4: 의제 + 컨텍스트
206
+ end
207
+ P1-->>RT: Opinion
208
+ P2-->>RT: Opinion
209
+ P3-->>RT: Opinion
210
+ P4-->>RT: Opinion
211
+
212
+ Note over RT: 2단계: 분류 취합
213
+ RT->>SM: opinions 전체 + 분류 지시
214
+ SM-->>RT: IdeaPool (common/divergent/unique)
215
+
216
+ RT-->>TF: IdeaPool
217
+ TF-->>C: IdeaPool
218
+ ```
219
+
220
+ ## IdeaPool 출력 구조
221
+
222
+ ```
223
+ IdeaPool
224
+ +-- agenda: 원본 의제
225
+ +-- common[]: 다수 모델이 동의하는 포인트
226
+ +-- divergent[]: 모델 간 입장이 다른 지점
227
+ | +-- topic: 쟁점
228
+ | +-- positions: {model_name: 해당 입장}
229
+ +-- unique[]: 한 모델만 제시한 고유 관점
230
+ +-- point
231
+ +-- source_model
232
+ ```
233
+
234
+ ## 핵심 설계 결정
235
+
236
+ ### 1. 2단계 파이프라인
237
+ - 1단계: 고성능 패널 모델들에 병렬 질의 (관점 수집)
238
+ - 2단계: 경량 모델이 raw opinions를 분류 취합 (토큰 압축)
239
+ - 메인 에이전트에는 구조화된 IdeaPool만 전달
240
+
241
+ ### 2. Summarizer 모델
242
+ - 분류 취합은 grok-4-1-fast-non-reasoning 사용
243
+ - XAI_API_KEY를 패널(grok-4-1)과 공유
244
+ - EnvConfig에서 summarizer_model로 별도 관리
245
+
246
+ ### 3. Python 패키지 (코어) + MCP wrapper (optional)
247
+ - 코어: import하여 프로그래머틱하게 호출
248
+ - MCP wrapper: Taskforce를 FastMCP 도구로 노출하는 thin wrapper
249
+ - `python -m taskforce.mcp_wrapper` 로 MCP 서버 실행 가능
250
+ - 입출력은 pydantic 모델 (JSON 직렬화 가능)
251
+
252
+ ### 4. 비동기 병렬 호출
253
+ - 패널 질의는 `asyncio.gather()`로 병렬 실행
254
+ - 개별 모델 타임아웃/실패 시 해당 모델만 제외
255
+
256
+ ### 5. 모델 레지스트리
257
+
258
+ **패널 (고성능)**
259
+
260
+ | 환경변수 | 프로바이더 | 모델 |
261
+ |----------|-----------|------|
262
+ | OPENAI_API_KEY | openai | gpt-5.4 |
263
+ | XAI_API_KEY | xai | grok-4-1 |
264
+ | ANTHROPIC_API_KEY | anthropic | claude-opus-4 |
265
+ | GEMINI_API_KEY | gemini | gemini-2.5-pro |
266
+
267
+ **Summarizer**
268
+
269
+ | 프로바이더 | 모델 | 비고 |
270
+ |-----------|------|------|
271
+ | xai | grok-4-1-fast-non-reasoning | XAI_API_KEY 공유 |
272
+
273
+ ### 6. caller_provider 기반 패널 제외
274
+ - 초기화 시 `caller_provider`를 받아 해당 프로바이더의 모델을 패널에서 제외
275
+ - 메인 에이전트와 동일 모델에 질의하는 것은 관점 다양성에 기여하지 않음
276
+ - 예: caller_provider="anthropic" -> claude-opus-4 패널에서 제외
277
+ - 키가 설정되어 있고 caller_provider와 다른 모델만 패널에 등록
278
+
279
+ ## 의존성
280
+
281
+ - `litellm` : 멀티 프로바이더 LLM 호출 통합
282
+ - `python-dotenv` : .env 파일 로드
283
+ - `pydantic` : 스키마 검증 + JSON 직렬화
284
+ - `asyncio` : 병렬 호출 (표준 라이브러리)
285
+ - `mcp` : MCP 서버 프레임워크 (optional, MCP wrapper용)
@@ -0,0 +1,15 @@
1
+ # 프로젝트 프로토콜
2
+
3
+ ## 구조 및 코딩 규칙
4
+
5
+ - Ln 구조: `@ff_coding_agent_protocol_md/for-agent-codingprotocol-ln-structure.md` 참조
6
+ - Python 코딩: `@ff_coding_agent_protocol_md/for-agent-codingprotocol-python.md` 참조
7
+ - 연구 프로토콜: `@ff_coding_agent_protocol_md/for-agent-research.md` 참조
8
+
9
+ ## 프로젝트 설명
10
+
11
+ [프로젝트 목적과 개요를 여기에 작성]
12
+
13
+ ## 추가 규칙
14
+
15
+ [프로젝트 특수 규칙이 있다면 여기에 작성]
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 taskforce contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,136 @@
1
+ Metadata-Version: 2.4
2
+ Name: ff-taskforce
3
+ Version: 0.1.0
4
+ Summary: Multi-LLM roundtable for diverse perspective gathering
5
+ Project-URL: Repository, https://github.com/gatesplan/taskforce
6
+ Project-URL: Issues, https://github.com/gatesplan/taskforce/issues
7
+ License: MIT
8
+ License-File: LICENSE
9
+ Keywords: agent,llm,mcp,multi-model,roundtable
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Requires-Python: >=3.10
18
+ Requires-Dist: litellm
19
+ Requires-Dist: loguru
20
+ Requires-Dist: pydantic>=2.0
21
+ Requires-Dist: python-dotenv
22
+ Provides-Extra: mcp
23
+ Requires-Dist: mcp; extra == 'mcp'
24
+ Description-Content-Type: text/markdown
25
+
26
+ # taskforce
27
+
28
+ AI agent-oriented multi-LLM roundtable library.
29
+
30
+ Multiple top-tier LLMs (GPT, Grok, Claude, Gemini) are queried in parallel with the same agenda, and the collected opinions are classified into **common / divergent / unique** perspectives, returned as a structured `IdeaPool`.
31
+
32
+ **This package is designed for AI agents, not for direct human use.**
33
+ The primary interface is the MCP wrapper (`roundtable_discuss` tool), which allows agents to invoke a roundtable discussion as a tool call. A Python API is also available for programmatic integration.
34
+
35
+ ## Quick Start
36
+
37
+ ### 1. Install
38
+
39
+ ```bash
40
+ pip install taskforce
41
+ ```
42
+
43
+ For MCP server support:
44
+
45
+ ```bash
46
+ pip install taskforce[mcp]
47
+ ```
48
+
49
+ ### 2. Set environment variables
50
+
51
+ At least two provider API keys are required (one will be excluded as the caller).
52
+ `XAI_API_KEY` is always required (used by the summarizer).
53
+
54
+ ```
55
+ OPENAI_API_KEY=sk-...
56
+ XAI_API_KEY=xai-...
57
+ ANTHROPIC_API_KEY=sk-ant-...
58
+ GEMINI_API_KEY=AI...
59
+ ```
60
+
61
+ ### 3. Use as MCP tool (recommended for agents)
62
+
63
+ Add to your MCP server config:
64
+
65
+ `TASKFORCE_CALLER_PROVIDER` is the provider of the agent that will call this tool.
66
+ The matching provider's model is excluded from the panel -- querying the same model that is already reasoning adds no diversity.
67
+ For example, if Claude Code is the caller, set it to `"anthropic"` so Claude is excluded from the panel.
68
+
69
+ ```json
70
+ {
71
+ "mcpServers": {
72
+ "taskforce": {
73
+ "command": "python",
74
+ "args": ["-m", "taskforce.mcp_wrapper"],
75
+ "env": {
76
+ "TASKFORCE_CALLER_PROVIDER": "anthropic"
77
+ }
78
+ }
79
+ }
80
+ }
81
+ ```
82
+
83
+ The agent can then call the `roundtable_discuss` tool with `agenda` and `context` parameters.
84
+
85
+ ### 4. Use as Python library
86
+
87
+ ```python
88
+ from taskforce import Taskforce
89
+
90
+ tf = Taskforce(caller_provider="anthropic")
91
+ pool = tf.discuss(
92
+ agenda="Evaluate the trade-offs of approach A vs B",
93
+ context="<detailed context here>"
94
+ )
95
+
96
+ # pool.common -- list[str]: points most models agree on
97
+ # pool.divergent -- list[DivergentPoint]: topics with differing positions
98
+ # pool.unique -- list[UniquePoint]: points raised by only one model
99
+ ```
100
+
101
+ ## Important Notes
102
+
103
+ - **Paid API calls.** Every `discuss()` invocation calls multiple LLM APIs in parallel. Agents should confirm with the user before calling.
104
+ - **caller_provider exclusion.** The model from the same provider as the calling agent is excluded from the panel to maximize perspective diversity.
105
+ - **XAI_API_KEY is mandatory.** The summarizer (grok-4-1-fast-non-reasoning) always uses the XAI key.
106
+ - **Rich context matters.** Input tokens are cheap. Provide as much context as possible -- specifications, constraints, background, decisions already made -- so the panel can give concrete, actionable opinions instead of generic advice.
107
+
108
+ ## API
109
+
110
+ ### `Taskforce(caller_provider, dotenv_path=None)`
111
+
112
+ - `caller_provider` (`str`): The LLM provider of the calling agent (e.g. `"anthropic"`, `"openai"`). That provider's model is excluded from the panel.
113
+ - `dotenv_path` (`str | None`): Path to `.env` file. Defaults to auto-discovery.
114
+
115
+ ### `Taskforce.discuss(agenda, context="") -> IdeaPool`
116
+
117
+ Synchronous wrapper. Queries the panel, summarizes, and returns an `IdeaPool`.
118
+
119
+ ### `Taskforce.discuss_async(agenda, context="") -> IdeaPool`
120
+
121
+ Async version for use in async contexts.
122
+
123
+ ### `IdeaPool`
124
+
125
+ | Field | Type | Description |
126
+ |-------|------|-------------|
127
+ | `agenda` | `str` | The original agenda |
128
+ | `common` | `list[str]` | Points most models agree on |
129
+ | `divergent` | `list[DivergentPoint]` | Topics with differing positions (`topic`, `positions: dict[model, position]`) |
130
+ | `unique` | `list[UniquePoint]` | Points from a single model (`point`, `source_model`) |
131
+ | `total_cost` | `float` | Total API cost (USD) |
132
+ | `total_tokens` | `int` | Total tokens consumed |
133
+
134
+ ## License
135
+
136
+ MIT
@@ -0,0 +1,111 @@
1
+ # taskforce
2
+
3
+ AI agent-oriented multi-LLM roundtable library.
4
+
5
+ Multiple top-tier LLMs (GPT, Grok, Claude, Gemini) are queried in parallel with the same agenda, and the collected opinions are classified into **common / divergent / unique** perspectives, returned as a structured `IdeaPool`.
6
+
7
+ **This package is designed for AI agents, not for direct human use.**
8
+ The primary interface is the MCP wrapper (`roundtable_discuss` tool), which allows agents to invoke a roundtable discussion as a tool call. A Python API is also available for programmatic integration.
9
+
10
+ ## Quick Start
11
+
12
+ ### 1. Install
13
+
14
+ ```bash
15
+ pip install taskforce
16
+ ```
17
+
18
+ For MCP server support:
19
+
20
+ ```bash
21
+ pip install taskforce[mcp]
22
+ ```
23
+
24
+ ### 2. Set environment variables
25
+
26
+ At least two provider API keys are required (one will be excluded as the caller).
27
+ `XAI_API_KEY` is always required (used by the summarizer).
28
+
29
+ ```
30
+ OPENAI_API_KEY=sk-...
31
+ XAI_API_KEY=xai-...
32
+ ANTHROPIC_API_KEY=sk-ant-...
33
+ GEMINI_API_KEY=AI...
34
+ ```
35
+
36
+ ### 3. Use as MCP tool (recommended for agents)
37
+
38
+ Add to your MCP server config:
39
+
40
+ `TASKFORCE_CALLER_PROVIDER` is the provider of the agent that will call this tool.
41
+ The matching provider's model is excluded from the panel -- querying the same model that is already reasoning adds no diversity.
42
+ For example, if Claude Code is the caller, set it to `"anthropic"` so Claude is excluded from the panel.
43
+
44
+ ```json
45
+ {
46
+ "mcpServers": {
47
+ "taskforce": {
48
+ "command": "python",
49
+ "args": ["-m", "taskforce.mcp_wrapper"],
50
+ "env": {
51
+ "TASKFORCE_CALLER_PROVIDER": "anthropic"
52
+ }
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ The agent can then call the `roundtable_discuss` tool with `agenda` and `context` parameters.
59
+
60
+ ### 4. Use as Python library
61
+
62
+ ```python
63
+ from taskforce import Taskforce
64
+
65
+ tf = Taskforce(caller_provider="anthropic")
66
+ pool = tf.discuss(
67
+ agenda="Evaluate the trade-offs of approach A vs B",
68
+ context="<detailed context here>"
69
+ )
70
+
71
+ # pool.common -- list[str]: points most models agree on
72
+ # pool.divergent -- list[DivergentPoint]: topics with differing positions
73
+ # pool.unique -- list[UniquePoint]: points raised by only one model
74
+ ```
75
+
76
+ ## Important Notes
77
+
78
+ - **Paid API calls.** Every `discuss()` invocation calls multiple LLM APIs in parallel. Agents should confirm with the user before calling.
79
+ - **caller_provider exclusion.** The model from the same provider as the calling agent is excluded from the panel to maximize perspective diversity.
80
+ - **XAI_API_KEY is mandatory.** The summarizer (grok-4-1-fast-non-reasoning) always uses the XAI key.
81
+ - **Rich context matters.** Input tokens are cheap. Provide as much context as possible -- specifications, constraints, background, decisions already made -- so the panel can give concrete, actionable opinions instead of generic advice.
82
+
83
+ ## API
84
+
85
+ ### `Taskforce(caller_provider, dotenv_path=None)`
86
+
87
+ - `caller_provider` (`str`): The LLM provider of the calling agent (e.g. `"anthropic"`, `"openai"`). That provider's model is excluded from the panel.
88
+ - `dotenv_path` (`str | None`): Path to `.env` file. Defaults to auto-discovery.
89
+
90
+ ### `Taskforce.discuss(agenda, context="") -> IdeaPool`
91
+
92
+ Synchronous wrapper. Queries the panel, summarizes, and returns an `IdeaPool`.
93
+
94
+ ### `Taskforce.discuss_async(agenda, context="") -> IdeaPool`
95
+
96
+ Async version for use in async contexts.
97
+
98
+ ### `IdeaPool`
99
+
100
+ | Field | Type | Description |
101
+ |-------|------|-------------|
102
+ | `agenda` | `str` | The original agenda |
103
+ | `common` | `list[str]` | Points most models agree on |
104
+ | `divergent` | `list[DivergentPoint]` | Topics with differing positions (`topic`, `positions: dict[model, position]`) |
105
+ | `unique` | `list[UniquePoint]` | Points from a single model (`point`, `source_model`) |
106
+ | `total_cost` | `float` | Total API cost (USD) |
107
+ | `total_tokens` | `int` | Total tokens consumed |
108
+
109
+ ## License
110
+
111
+ MIT
@@ -0,0 +1,37 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "ff-taskforce"
7
+ version = "0.1.0"
8
+ description = "Multi-LLM roundtable for diverse perspective gathering"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.10"
12
+ keywords = ["llm", "multi-model", "roundtable", "mcp", "agent"]
13
+ classifiers = [
14
+ "Development Status :: 3 - Alpha",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.10",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
+ ]
22
+ dependencies = [
23
+ "litellm",
24
+ "python-dotenv",
25
+ "pydantic>=2.0",
26
+ "loguru",
27
+ ]
28
+
29
+ [project.optional-dependencies]
30
+ mcp = ["mcp"]
31
+
32
+ [project.urls]
33
+ Repository = "https://github.com/gatesplan/taskforce"
34
+ Issues = "https://github.com/gatesplan/taskforce/issues"
35
+
36
+ [tool.hatch.build.targets.wheel]
37
+ packages = ["src/taskforce"]
@@ -0,0 +1,3 @@
1
+ from .l4.taskforce_facade import Taskforce
2
+
3
+ __all__ = ['Taskforce']
@@ -0,0 +1,16 @@
1
+ # taskforce
2
+
3
+ ## l1
4
+ - schema: 데이터 모델 (ModelEntry, Opinion, IdeaPool)
5
+
6
+ ## l2
7
+ - config: .env 로드, 모델 레지스트리, caller 제외 로직
8
+ - panelist: LiteLLM 래퍼, 개별 모델 async 호출
9
+ - session_logger: 세션 전문 로그 (~/.taskforce/logs/)
10
+ - cost_logger: 비용 요약 로그 (~/.taskforce/cost_logs/)
11
+
12
+ ## l3
13
+ - roundtable: 병렬 질의 + summarizer 분류 취합
14
+
15
+ ## l4
16
+ - taskforce_facade: 최상위 퍼사드, 초기화/discuss/로그 기록
@@ -0,0 +1,3 @@
1
+ from .schema import ModelEntry, Opinion, DivergentPoint, UniquePoint, IdeaPool
2
+
3
+ __all__ = ['ModelEntry', 'Opinion', 'DivergentPoint', 'UniquePoint', 'IdeaPool']
@@ -0,0 +1,8 @@
1
+ # l1
2
+
3
+ ## schema
4
+ ModelEntry(provider: str, model_id: str, api_key: str, display_name: str)
5
+ Opinion(model_name: str, content: str)
6
+ DivergentPoint(topic: str, positions: dict[str, str])
7
+ UniquePoint(point: str, source_model: str)
8
+ IdeaPool(agenda: str, common: list[str], divergent: list[DivergentPoint], unique: list[UniquePoint])
@@ -0,0 +1,3 @@
1
+ from .schema import ModelEntry, Opinion, DivergentPoint, UniquePoint, IdeaPool
2
+
3
+ __all__ = ['ModelEntry', 'Opinion', 'DivergentPoint', 'UniquePoint', 'IdeaPool']