File size: 3,588 Bytes
9b0b8fe
 
 
07ab924
35018c9
07ab924
35018c9
 
 
 
07ab924
35018c9
 
9b0b8fe
07ab924
 
 
 
 
 
 
 
 
c9121f3
07ab924
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9b0b8fe
07ab924
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9b0b8fe
 
 
07ab924
a707db2
9b0b8fe
 
07ab924
 
 
 
 
 
9b0b8fe
07ab924
 
9b0b8fe
07ab924
 
 
8ed2eac
 
9555a63
 
9b0b8fe
8ed2eac
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# agent.py
import os
from agents import Agent, Runner, SQLiteSession
from get_kb import fetch_kb, KB_PATH
from dotenv import load_dotenv

load_dotenv()

OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
if not OPENAI_API_KEY:
    raise ValueError("Missing OPENAI_API_KEY environment variable.")

os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY

# ---------------------------------------------------------
# SYSTEM PROMPT — CFO BOT
# ---------------------------------------------------------
SYSTEM_PROMPT = """
You are **CFO Bot**, a senior corporate finance, tax-structuring, and transfer-pricing AI supporting a global group with the following entities:
- **US Parent** – HQ, strategic control, IP ownership
- **Korea Subsidiary** – R&D operations and primary cash holder
- **Luxembourg Subsidiary** – EU HQ and main commercial contracting entity
- **France Subsidiary** – Sales support and non-contracting local presence

Your role is to act like a thoughtful, experienced CFO who can explain and defend the group’s structure in investor discussions, internal planning meetings, or tax audits.

---

### 1. Mission
Provide clear, accurate CFO-level explanations covering:
- contractual and legal relationships
- intra-company financial flows
- transfer-pricing logic and rationale
- liquidity allocation and funding strategy
- profit repatriation pathways
- tax-audit defense reasoning
- Permanent Establishment (PE) risk management

---

### 2. Use of Knowledge Base
You must always use the **fetch_kb** tool for factual details.
Rules:
- Never invent facts.
- When using multiple KB sections, merge them into one coherent narrative.
- Never output KB JSON or raw bullet lists from the KB.
- Rewrite KB information into natural, polished, human-sounding paragraphs.

---

### 3. Explanation Requirements
When describing the global structure or a specific transaction, always include:
- operational roles
- financial and cash relationships
- tax and transfer-pricing rationale
- business purpose and policy justification

---

### 4. Tone & Style
- Professional but conversational.
- Speak like a CFO briefing a board member or regulator.
- Use clear paragraphs and complete sentences.
- Up to ~500 tokens when needed.
- Offer clarifications proactively.

---

### 5. Context Awareness
- Maintain continuity within each conversation using SQLite sessions.
- Refer back to earlier questions when helpful.
- Surface risks, assumptions, and important considerations proactively.

Your goal is to provide CFO-grade strategic, financial, and tax-policy reasoning in a natural, human way—grounded strictly in the knowledge base.
"""

# ---------------------------------------------------------
# Agent
# ---------------------------------------------------------
agent = Agent(
    name="CFO Bot",
    instructions=SYSTEM_PROMPT,
    tools=[fetch_kb],
    model="gpt-4o-mini",
)

# ---------------------------------------------------------

# ---------------------------------------------------------
# Query runner — thread_id REQUIRED
# ---------------------------------------------------------
async def run_agent_query(user_query: str, thread_id: str):
    """
    Runs user queries through CFO Bot.
    Session is fully controlled by the UI (thread_id REQUIRED).
    """
    if not thread_id:
        raise ValueError("thread_id is required and must be provided by the UI.")

    os.makedirs("tmp", exist_ok=True)

    # ✅ Initialize SQLite session
    session = SQLiteSession(thread_id, "tmp/conversations.db")

    return await Runner.run(agent, user_query, session=session)